android处理消息机制----Handler

在android开发过程中,我们经常有更新UI的操作。如网络请求后,更新UI控件。此时我们第一想法就是用Handler,确实如此。由于Android开发规范限制,我们不能在非主线程(UI线程,即ActivityThread)里面直接操作UI控件,否则会出现异常,Only the original thread that created a view....(Android线程并不是线程安全的,在多线程中并发操作UI控件可能会发生不可预计的问题)。

现在我并不是想讲Handler 如何操作UI控件,而是为什么Handler可以操作UI控件。来自官方文档一段话

A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.

说人话就是:Handler可以将一个任务切换到Handler所在的线程中去执行任务。

为啥android需要提供一个在某个线程中执行任务这种功能?这个就解决了在非UI线程中操作UI控件会抛出异常,这就是Handler存在的意义。Handler可以把UI控件更新操作切换到UI主线程中执行,这个就决解了在子线程中如何更新UI主线程控件的问题。总之一句话:Handler可以将Handler中的业务逻辑切换到创建Handler所在的线程中执行

现在我们知道Handler是将控件操作切换至UI主线程中执行,但是,这个如何切换的呢?具体是怎么切换的呢?

我的理解是这样的:整个流程涉及到Looper、MessageQueue、Handler。

一,Handler通过send方法发送一个消息Message,发送到当前线程的MessageQueue中,

二,Looper 通过loop方法不断地从MessageQueue中抽取Message(在主线程中,默认是包含Looper)

 public static final void loop() {
 72         Looper me = myLooper();//从该线程中取出对应的looper对象
 73         MessageQueue queue = me.mQueue;//取消息队列对象...
 74         while (true) {
 75             Message msg = queue.next(); // might block取消息队列中的一个待处理消息..
 76             //if (!me.mRun) {//是否需要退出?mRun是个volatile变量,跨线程同步的,应该是有地方设置它。
 77             //    break;
 78             //}
 79             if (msg != null) {
 80                 if (msg.target == null) {
 81                     // No target is a magic identifier for the quit message.
 82                     return;
 83                 }
 84                 if (me.mLogging!= null) me.mLogging.println(
 85                         ">>>>> Dispatching to " + msg.target + " "
 86                         + msg.callback + ": " + msg.what
 87                         );
 88                 msg.target.dispatchMessage(msg);
 89                 if (me.mLogging!= null) me.mLogging.println(
 90                         "<<<<< Finished to    " + msg.target + " "
 91                         + msg.callback);
 92                 msg.recycle();
 93             }
 94         }
 95     }
以上可以看到,当有loop检测有message信息的时候, 会调用msg.target.dispatchMessage(msg);这个msg.target是指Handler。

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}
handleMessage方法是不是有点熟悉?对,就是Handler的回调方法

这个流程指出了,handler发出消息给messageQueue,looper不断从messageQueue里取出消息,然后执行handlerMessage方法。handlerMessage方法具体的实现在Handler回调里面。

结束了?? “Handler是将控件操作切换至UI主线程中执行”这句话还没解释的通啊。

通过网上资料查询,我知道在ActivityThread创建时,会初始化Looper,也就是说默认情况下Looper在主线程中会创建的。

那我们现在明白,在子线程中可以通过Handler更新UI控件的原因了。Handler可以将Handler中的业务逻辑切换到创建Handler所在的线程中执行。而Looper恰恰是属于主线程的。


下一篇说说Handler、MessageQueue、Looper

你可能感兴趣的:(移动开发)