Android的消息处理(Handler相关)

  首先Message(消息)类不用多说,内部用what(啥)属性来存放标识符,用obj(对象)来存放要携带的数据,用target(目标)来存放目标Handler。

  所以需要有一个Handler(句柄)类来处理Message,方法是调用Handler类中的sendMessage(Message)方法,我之前一直觉得这个方法名的逻辑很奇怪,现在懂了,因为知道了另一个类:

  MessageQueue(消息队列),在调用sendMessage之后Handler会依次调用两个不是重载但跟重载也差不多的内部方法,最后像这样

sent = queue.enqueueMessage(msg, uptimeMillis);

把Message发送(send)给内部创建的一个MessageQueue对象,同时把Message中的target属性设置为自己。

  这时又要说到另一个类,Looper(循环器)。程序运行的时候安卓会在主线程里创建一个Looper,

 1     /**
 2      * Initialize the current thread as a looper, marking it as an
 3      * application‘s main looper. The main looper for your application
 4      * is created by the Android environment, so you should never need
 5      * to call this function yourself.  See also: {@link #prepare()}
 6      */
 7     public static void prepareMainLooper() {
 8         prepare(false);
 9         synchronized (Looper.class) {
10             if (sMainLooper != null) {
11                 throw new IllegalStateException("The main Looper has already been prepared.");
12             }
13             sMainLooper = myLooper();
14         }
15     }
系统调用

它以for死循环的方式不断尝试从队列中取出Message,

Message msg = queue.next();

取到了就调用这个Message中的target中存放的那个Handler的dispatchMessage(Message)方法。像这样:

msg.target.dispatchMessage(msg);

  Handler用这个方法稍微进行一下判断,之后就转交给自己的handleMessage(Message)方法来处理消息,这个方法和onCreate一样是由程序员重写,由系统调用的。

  剩下的就很简单了,handleMessage方法是程序员自己写的,想做点什么都行。

  通常是根据Message中的what来switch一下,对于不同消息来源做出不同反应就可以啦。

 


 

 

那么总结一下

  明面上程序员做两件事。

  首先是创建Handler,重写好方法,决定用它来做点什么;

  后面的分为两种情况。

  如果调用Handler的时候需要携带信息,就用Message.obtain()方法或new关键字得到Message对象,然后使用Handler对象的sendMessage(Message)方法交由Handler处理。

  如果并不需要携带额外信息,只需要通知Handler有事要做,就不需要自己得到Message对象,直接使用Handler对象的sendEmptyMessage(int)方法,Handler会像这样

Message msg = Message.obtain();
msg.what = what;

自己创建一个Message对象,并用方法中传入的int值作为Message的what属性。

         第一步,定义Handler。

         第二步,发送消息。

         这样。

 


 

PS:

  如果要在主线程之外使用Handler要注意一个问题。

  首先按照上面说的,消息是由Looper从队列中取出并分发的,只管自己的线程。可是主线程中使用的Looper是安卓系统创建的,用户新建线程的时候并不会自动创建一个新的Looper,所以Looper告诉你

final Looper me = myLooper();
if (me == null) {
     throw new RuntimeException("No Looper; Looper.prepare() wasn‘t called on this thread.");
}

这个,Handler告诉你

mLooper = Looper.myLooper();
if (mLooper == null) {
    throw new RuntimeException(
        "Can‘t create handler inside thread that has not called Looper.prepare()");
}

这个。

  因此,要在新线程里创建Handler就需要调用Looper.prepare()方法来准备好一个Looper,这个方法会自动调用内部的重载方法,不需要担心。

    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

  自己调用的时候参数是true,系统调用的时候是false,总之不需要在意。

 

 

  Handler用来让其他线程修改UI啊,这个不用我说吧。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。