Message Handler Looper

来源:互联网 发布:怎样与淘宝买家联系 编辑:程序博客网 时间:2024/05/24 07:46

一、Message

Message创建方式有两种,一种是new Message(),开销较大,另外一种是Message.obtain(),使用回收但是没有被释放的message对象,减少开销,有点类似Adapter中的ConvertView与ViewHolder,一般使用Message msg = Handler.obtain(),事实上也是调用Message.Obtain().

Handler.class

/**     * Returns a new {@link android.os.Message Message} from the global message pool. More efficient than     * creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this).     *  If you don't want that facility, just call Message.obtain() instead.     */    public final Message obtainMessage()    {        return Message.obtain(this);    }

Message.class

    /**     * Return a new Message instance from the global pool. Allows us to     * avoid allocating new objects in many cases.     */    public static Message obtain() {        synchronized (sPoolSync) {            if (sPool != null) {                Message m = sPool;                sPool = m.next;                m.next = null;                sPoolSize--;                return m;            }        }        return new Message();    }

通过recycle回收的Message对象

Message.class

    /**     * Return a Message instance to the global pool.  You MUST NOT touch     * the Message after calling this function -- it has effectively been     * freed.     */    public void recycle() {        clearForRecycle();        synchronized (sPoolSync) {            if (sPoolSize < MAX_POOL_SIZE) {                next = sPool;                sPool = this;                sPoolSize++;            }        }    }

二、Handler

Handler用来发送和处理Message,典型的方法有handleMessage(Message),sendMessage(Message)

SendMessage(Message)

   public final boolean sendMessage(Message msg)    {        return sendMessageDelayed(msg, 0);    }

sendMessageDelayed(Message msg,long)

    public final boolean sendMessageDelayed(Message msg, long delayMillis)    {        if (delayMillis < 0) {            delayMillis = 0;        }        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);    }

sendMessageAtTime(Message, long)

 public boolean sendMessageAtTime(Message msg, long uptimeMillis) {        MessageQueue queue = mQueue;        if (queue == null) {            RuntimeException e = new RuntimeException(                    this + " sendMessageAtTime() called with no mQueue");            Log.w("Looper", e.getMessage(), e);            return false;        }        return enqueueMessage(queue, msg, uptimeMillis);    }
sendMessage实际上就是将msg放入到mQueue;


handleMessage(Message)

    /**     * Subclasses must implement this to receive messages.     */    public void handleMessage(Message msg) {    }

handleMessage(Message)是一个空方法,需要子类来实现


三、Looper

Looper,消息循环,主要方法loop(),无限循环去mQueue中取消息交给Handler

 /**     * 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.recycle();        }    }
其中msg.target就是Handler,而dispatch就是调用了handMessage()

最后将已经出队列的msg回收到pool中备用

四、关系

初始化&发送消息

Handler handler;Looper.prepare();handler = new Handler();Message msg = handler.obtainMessage();msg.what = 1;handler.sendMessage(msg);Looper.loop();


处理消息

class MyHandler extends Handler{@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubswitch (msg.what) {}}}

逐步分析如何实现

Loop.prepare();//实例化Looper,在构造函数中建立一个消息队列MessageQueue,并绑定当前的Thread,所以在哪个线程里实例化Looper,对应的消息队列就依附与那个线程

private Looper() {          mQueue = new MessageQueue();          mRun = true;          mThread = Thread.currentThread();      }  
handler = new Handler();//主要是通过Looper获取mQueue,所以实例化Handler之前必须确保当前线程已经绑定了一个Looper,否则如源码所示,抛出异常“can't create handler inside thread that has not called Looper.prepare()”

/**      * Default constructor associates this handler with the queue for the      * current thread.      *      * If there isn't one, this handler won't be able to receive messages.      */      public Handler() {          if (FIND_POTENTIAL_LEAKS) {              final Class<? extends Handler> 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();          if (mLooper == null) {              throw new RuntimeException(                  "Can't create handler inside thread that has not called Looper.prepare()");          }          mQueue = mLooper.mQueue;          mCallback = null;      }  

Message msg = handler.obtain();//参照Message部分介绍
msg.what = 1;


handler.sendMessage(msg);//将msg放入队列mQueue

        return enqueueMessage(queue, msg, uptimeMillis);


Looper.loop()//循环遍历mQueue,有msg就交给handler处理

public static void loop() {        final MessageQueue queue = me.mQueue;        for (;;) {            Message msg = queue.next(); // might block            msg.target.dispatchMessage(msg);            msg.recycle();        }    }
...




原创粉丝点击