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

来源:互联网 发布:公知日杂什么意思 编辑:程序博客网 时间:2024/06/09 18:51

在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

1 0
原创粉丝点击