Looper、handler、message小结

来源:互联网 发布:一级位面淘宝网txt 编辑:程序博客网 时间:2024/06/03 03:20

Looper的作用:



      looper作用概括
Looper不断的获取Messagequeue中的一个message,然后由hander来处理

       Looper的主要方法

Looper.prepare();方法:为每个线程创建一个唯一的looper,并与当前线程联系起来。

Loop.prepare():这个方法只能调用一次,保证每个Thread只保存一个looper。


 public static void prepare() {        prepare(true);    }    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));    }


创建一个looper的时候会创建一个MessageQueue(消息队列)


 private Looper(boolean quitAllowed) {        mQueue = new MessageQueue(quitAllowed);        mThread = Thread.currentThread();    }

Looper.loop();方法:

不断的获取MessageQueue的message,并通过message.taget.dispatchmessage(msg) 将消息发送出去。


  /**     * Run the message queue in this thread. Be sure to call     * {@link #quit()} to end the loop.     */    public static void loop() {        final Looper me = myLooper();        if (me == null) {            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");        }        final MessageQueue queue = me.mQueue;        // Make sure the identity of this thread is that of the local process,        // and keep track of what that identity token actually is.        Binder.clearCallingIdentity();        final long ident = Binder.clearCallingIdentity();        for (;;) {            Message msg = queue.next(); // might block            if (msg == null) {                // No message indicates that the message queue is quitting.                return;            }            // This must be in a local variable, in case a UI event sets the logger            Printer logging = me.mLogging;            if (logging != null) {                logging.println(">>>>> Dispatching to " + msg.target + " " +                        msg.callback + ": " + msg.what);            }            msg.target.dispatchMessage(msg);            if (logging != null) {                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);            }            // Make sure that during the course of dispatching the            // identity of the thread wasn't corrupted.            final long newIdent = Binder.clearCallingIdentity();            if (ident != newIdent) {                Log.wtf(TAG, "Thread identity changed from 0x"                        + Long.toHexString(ident) + " to 0x"                        + Long.toHexString(newIdent) + " while dispatching to "                        + msg.target.getClass().getName() + " "                        + msg.callback + " what=" + msg.what);            }            msg.recycleUnchecked();        }    }


Hander:是如何与message联系起来的?



handler是怎么接收到message的?


 /**     * Handle system messages here.     */    public void dispatchMessage(Message msg) {        if (msg.callback != null) {            handleCallback(msg);        } else {            if (mCallback != null) {                if (mCallback.handleMessage(msg)) {                    return;                }            }            handleMessage(msg);        }    }



message通过message.taget.dispatchmessage(msg) ,handler的dispatchMessage()方法如下:通过handlerMessage将消息发送处理。

这里对消息的处理除了handlerMessage(),还有一个mCallback.handleMessage(msg),还有的是msg.callback:



所以handler处理消息的方法有三种,下面是常见两种,msg.callback用的比较少:

1.

handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);}};


2.

handler = new Handler(new Handler.Callback() {@Overridepublic boolean handleMessage(Message msg) {return false;}});



handler什么时候添加looper?



1:主线程的时候实例化handler时已经在ui主线程添加了looper,所以不用添加looper,而非主线程的时候实例化handler时必须添加looper,否则会报错误;throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");


  1. new Thread()  
  2.         {  
  3.             private Handler handler;  
  4.             public void run()  
  5.             {  
  6.   
  7.                 Looper.prepare();  
  8.                   
  9.                 handler = new Handler()  
  10.                 {  
  11.                     public void handleMessage(android.os.Message msg)  
  12.                     {  
  13.                     };  
  14.                 };
  15.                  Looper.loop();
  16. }


这里,Looper只有两句代码,概括起来有三个步骤:

1.looper的准备工作(prepare)。这个使Looper与handler挂钩。

2.创建处理消息的hanler。

3.looper开始运作(loop)。不断的从消息队列中取出消息,发给hanler处理。


2.整个过程:

通过Looper.prepare();给当前线程保存一个唯一的Looper对象,该looper对象创建了一个Message队列。然后handler实例化时获取到当前线程的looper对象,并拿到该looper对象的消息队列。handler调用 sendMessage()方法过程中调用到enqueueMessage()方法,并将要发送的message的target指向当前的发送消息的handler,同时将消息压入要发送消息的handler的消息队列(也就是当前线程looper的消息队列,因为它于handler已经挂钩了),最后looper.loop();该方法不断获取到消息队列的Message,并通过message.taget.dispatchmessage(msg)将消息发送出去。handler可以通过handlerMessage()也可以通过Handler.Callback()获取到发送过来的Message,然后处理。


looper作用:创建当前线程的looper对象,该对象包含了一个消息队列,然后不断的获取消息队列的消息发送出去。
handler作用:获取到当前线程的looper的消息队列,发送消息时将消息的target(相当于要发送的地址)指定,并将消息压入消息队列中。

Handler发送消息有主要有两种,post系列、send系列:

post系列:

public final boolean post(Runnable r):

postAtTime(Runnable r, long uptimeMillis) 

postDelayed(Runnable r, long delayMillis)


send系列主:要是发送message。

post可以设置发送时间,可以延迟发送,除了handler之外,View也有post的方法:

imageView.post(new Runnable() {@Overridepublic void run() {mAnimation.start(); }});

所以对一些view的ui操作可以通过post更新,其原理是:

View.post(Runnable)方法。在post(Runnable action)方法里,View获得当前线程(即UI线程)的Handler,然后将action对象post到Handler里。在Handler里,它将传递过来的action对象包装成一个Message(Message的callback为action),然后将其投入UI线程的消息循环中。在Handler再次处理该Message时,有一条分支(未解释的那条)就是为它所设,直接调用runnable的run方法。而此时,已经路由到UI线程里。


它们之间的关系:


1. Looper不断的获取Messagequeue中的一个message,然后由hander来处理

2.每个thread对应一个looper

3.每个looper只对应一个messagequeue

4.每个messagequeue中有多个message

5.每个message中最多指定一个handler来处理






0 0