handler源码分析


handler机制

简单总结下, handler机制提供了跨线程之前的通信方式。
先来看一段简单的代码示例,线程A创建handler对象,调用looper.prepare(), 创建Looper对象, 和MessageQueue,绑定到当前线程。然后启动looper轮询,sendMessageDelayed()会将Message 加入MessageQueue,然后线程B处理Message
可以发送message给到创建Handler的那个线程,最终由他handlerMessage。

class LoopThread extends Thread {
        public Handler mHandler = null;

        public LoopThread(String threadName) {
            super(threadName);
        }

        @Override
        public void run() {
            Looper.prepare();
            mHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                        case RESPONSE:
                            System.out.println("接受到[" + Thread.currentThread().getName() + "]发送的消息");
                            break;
                        default:
                            break;
                    }
                }
            };
            Looper.loop();
        }
    }

    //threadB处理消息
    final LoopThread threadB = new LoopThread("ThreadB");
    threadB.start();


    //threadA发送消息
    Thread threadA = new Thread(new Runnable() {
        @Override
        public void run() {
            Message msg = new Message();
            msg.what = RESPONSE;
            threadB.mHandler.sendMessage(msg);
            System.out.println("["+Thread.currentThread().getName() + "]发送消息");
        }
    }, "ThreadA");

    threadA.start();

接下来分析下handler的源码,省略无用方法, 讲解主要的方法,以此来理解handler的机制。

handler sendMessage() 将消息加入message队列

//handler.post()
//调用sendMessageDelayed, 最终调用enqueueMessage
public final boolean post(Runnable r)
{
   return  sendMessageDelayed(getPostMessage(r), 0);
}

//Message.obtain() 利用对象池的方式获得Message 对象, 并且将Runnable 设置为Message对象的callback
private static Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;
    return m;
}

//将msg 加入到MessageQueue
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    //msg.target 保持当前handler对象的引用
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}

looper 循环处理消息队列

主线程默认就会调用如下两个方法。如果在子线程使用handler就要在前后加入这两个方法,这样就会在子线程中轮询MeesageQueue了。

looper.prepare()

创建Looper对象, 创建MessageQueue, 并且Looper持有MessageQueue的引用,当前线程持有Looper对象引用

//创建一个looper对象, 并且设置为ThreadLocal
private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    //这里会把new 出来的Looper对象保存到当前线程中
    sThreadLocal.set(new Looper(quitAllowed));
}

//new Looper() 创建MessageQueue, 并且保留当前线程
private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}

looper.loop()

遍历MeesageQueue, 调用handler的 dispatchMessage()处理Message

//开始循环处理meesageQueue
public static void loop() {
    //首先获取ThreadLocal的Looper对象
    final Looper me = myLooper();
    
    //获取Looper对象引用的MeesageQueue
    final MessageQueue queue = me.mQueue;

    //无限循环
    for (;;) {
        //有消息取, 否则阻塞
        Message msg = queue.next(); // might block
        if (msg == null) {
            return;
        }

        //调用Message对象引用的handler对象的dispatchMessage()分发消息
        msg.target.dispatchMessage(msg);
      
    }
}

handler处理Message

这里如果msg 有callback则先执行msg的callback;
否则执行handler的callback的handleMessage;
否则执行handler子类的handleMessage;

public void dispatchMessage(Message msg) {
    //如果Message的回调不为空, 则回调callback
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        //处理Message
        handleMessage(msg);
    }
}

private static void handleCallback(Message message) {
    message.callback.run();
}

//handlerMessage为空, 由子类去实现
public void handleMessage(Message msg) {
}

主线程默认就有一个Looper对象, 在ActivityThread

public static void main(String[] args) {
    Looper.prepareMainLooper();

    ActivityThread thread = new ActivityThread();
    thread.attach(false);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    AsyncTask.init();

    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }

    Looper.loop();
}

handler构造方法

public Handler(Callback callback, boolean async) {
    if (FIND_POTENTIAL_LEAKS) {
        final Class klass = getClass();
        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                (klass.getModifiers() & Modifier.STATIC) == 0) {
            Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                klass.getCanonicalName());
        }
    }
    
    mLooper = Looper.myLooper();
    //这里如果在子线程使用handler 不调用looper.prepare(), 则会报如下错误。这个应该很多人遇到过吧?
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

HandlerThread

主要作用是很简单的创建一个带looper的线程,方便的使用handler的机制做异步处理。
但是他只有一个线程,适合串行任务,不适合做并行任务。比如网络IO阻塞时间比较长的,推荐使用线程池或者asyncTask+线程池来处理。
源码:

public class HandlerThread extends Thread {
    public HandlerThread(String name, int priority) {
        super(name);
        //可以设置线程优先级,因为默认的优先级是比较高的,所以可以设置低一点
        mPriority = priority;
    }
    
    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

示例:

HandlerThread workerThread = new HandlerThread("workerThread", Process.THREAD_PRIORITY_BACKGROUND);
    workerThread.start();
    mHandler = new Handler(workerThread.getLooper());

你可能感兴趣的:(handler源码分析)