Handler

Message:消息;其中包含了消息ID,消息對象以及處理的數據等,由MessageQueue統一列隊,終由Handler處理異步

Handler:處理者;負責Message發送消息及處理。Handler經過與Looper進行溝通,從而使用Handler時,須要實現handlerMessage(Message msg)方法來對特定的Message進行處理,例如更新UI等(主線程中才行)async

MessageQueue:消息隊列;用來存放Handler發送過來的消息,並按照FIFO(先入先出隊列)規則執行。固然,存放Message並不是實際意義的保存,而是將Message以鏈表的方式串聯起來的,等Looper的抽取。ide

Looper:消息泵,不斷從MessageQueue中抽取Message執行。所以,一個線程中的MessageQueue須要一個Looper進行管理。Looper是當前線程建立的時候產生的(UI Thread即主線程是系統幫忙建立的Looper,而若是在子線程中,須要手動在建立線程後當即建立Looper[調用Looper.prepare()方法])。也就是說,會在當前線程上綁定一個Looper對象。函數

Thread:線程;負責調度消息循環,即消息循環的執行場所。oop

 

 

知識要點 測試

1、說明ui

一、handler應該由處理消息的線程建立。this

二、handler與建立它的線程相關聯,並且也只與建立它的線程相關聯。handler運行在建立它的線程中,因此,若是在handler中進行耗時的操做,會阻塞建立它的線程。spa

2、一些知識點線程

一、Android的線程分爲有消息循環的線程和沒有消息循環的線程,有消息循環的線程通常都會有一個Looper。主線程(UI線程)就是一個消息循環的線程。

二、獲取looper:

Looper.myLooper();      //得到當前的Looper

Looper.getMainLooper () //得到UI線程的Lopper

三、Handle的初始化函數(構造函數),若是沒有參數,那麼他就默認使用的是當前的Looper,若是有Looper參數,就是用對應的線程的Looper。

四、若是一個線程中調用Looper.prepare(),那麼系統就會自動的爲該線程創建一個消息隊列,而後調用 Looper.loop();以後就進入了消息循環,這個以後就能夠發消息、取消息、和處理消息。

 

消息處理機制原理:

 

 

 

 

1、大體流程:

在建立Activity以前,當系統啓動的時候,先加載ActivityThread這個類,在這個類中的main函數,調用了Looper.prepareMainLooper();方法進行初始化Looper對象;而後建立了主線程的handler對象(Tips:加載ActivityThread的時候,其內部的Handler對象[靜態的]還未建立);隨後才建立了ActivityThread對象;最後調用了Looper.loop();方法,不斷的進行輪詢消息隊列的消息。也就是說,在ActivityThread和Activity建立以前(一樣也是Handler建立以前,固然handler因爲這二者初始化),就已經開啓了Looper的loop()方法,不斷的進行輪詢消息。須要注意的是,這個輪詢的方法是阻塞式的,沒有消息就一直等待(實際是等着MessageQueue的next()方法返回消息)。在應用一執行的時候,就已經開啓了Looper,並初始化了Handler對象。此時,系統的某些組件或者其餘的一些活動等發送了系統級別的消息,這個時候主線程中的Looper就能夠進行輪詢消息,並調用msg.target.dispatchMessage(msg)(msg.target即爲handler)進行分發消息,並經過handler的handleMessage方法進行處理;因此會優於咱們本身建立的handler中的消息而處理系統消息。

 

0、準備數據和對象:

①、若是在主線程中處理message(即建立handler對象),那麼如上所述,系統的Looper已經準備好了(固然,MessageQueue也初始化了),且其輪詢方法loop已經開啓。【系統的Handler準備好了,是用於處理系統的消息】。【Tips:若是是子線程中建立handler,就須要顯式的調用Looper的方法prepare()和loop(),初始化Looper和開啓輪詢器】

②、經過Message.obtain()準備消息數據(實際是從消息池中取出的消息)

③、建立Handler對象,在其構造函數中,獲取到Looper對象、MessageQueue對象(從Looper中獲取的),並將handler做爲message的標籤設置到msg.target上

一、發送消息:sendMessage():經過Handler將消息發送給消息隊列

二、給Message貼上handler的標籤:在發送消息的時候,爲handler發送的message貼上當前handler的標籤

三、開啓HandlerThread線程,執行run方法。

四、在HandlerThread類的run方法中開啓輪詢器進行輪詢:調用Looper.loop()方法進行輪詢消息隊列的消息

【Tips:這兩步須要再斟酌,我的認爲這個類是本身手動建立的一個線程類,Looper的開啓在上面已經詳細說明了,這裏是說本身手動建立線程(HandlerThread)的時候,纔會在這個線程中進行Looper的輪詢的】

五、在消息隊列MessageQueue中enqueueMessage(Message msg, long when)方法裏,對消息進行入列,即依據傳入的時間進行消息入列(排隊)

六、輪詢消息:與此同時,Looper在不斷的輪詢消息隊列

七、在Looper.loop()方法中,獲取到MessageQueue對象後,從中取出消息(Message msg = queue.next())

八、分發消息:從消息隊列中取出消息後,調用msg.target.dispatchMessage(msg);進行分發消息

九、將處理好的消息分發給指定的handler處理,即調用了handler的dispatchMessage(msg)方法進行分發消息。

十、在建立handler時,複寫的handleMessage方法中進行消息的處理

十一、回收消息:在消息使用完畢後,在Looper.loop()方法中調用msg.recycle(),將消息進行回收,即將消息的全部字段恢復爲初始狀態

 

測試代碼:

/**

 * Handler 構造函數測試

 */

public class HandlerConstructorTest extends Activity {

       private Handler handler1 = new Handler(new Callback() {

              @Override

              public boolean handleMessage(Message msg) {

                     System.out.println("使用了Handler1中的接口Callback");

                     return false;           // 此處,若是返回 false,下面的 handlerMessage方法會執行,true ,下面的不執行

              }

       });

      

       private Handler handler2 = new Handler() {

              public void handleMessage(Message msg) {

                     System.out.println("Handler2");

              }

       };

 

       protected void onCreate(Bundle savedInstanceState) {

              super.onCreate(savedInstanceState);

              //消息1

     Message obtain1 = Message.obtain();

              obtain1.obj = "sendMessage";

              obtain1.what = 1;

              handler1.sendMessage(obtain1);

              //消息2

              Message obtain2 = handler2.obtainMessage();

              handler2.sendMessage(obtain2);    //①

//            handler2.dispatchMessage(obtain2);      //②

       }

}

 

 

2、詳細解釋:

1、準備Looper對象

兩種狀況初始化Looper對象:

1)在主線程中不須要顯式的建立Looper對象,直接建立Handler對象便可;由於在主線程ActivityThread的main函數中已經自動調用了建立Looper的方法:Looper.prepareMainLooper();,並在最後調用了Looper.loop()方法進行輪詢。

2)若是在子線程中建立Handler對象,須要建立Looper對象,即調用顯式的調用Looper.prepare()

初始化Looper的工做:

1)初始化Looper對象:經過調用Looper.prepare()初始化Looper對象,在這個方法中,新建立了Looper對象

2)將Looper綁定到當前線程:在初始化中,調用sThreadLocal.set(new Looper(quitAllowed))方法,將其和ThreadLocal進行綁定

在ThreadLocal對象中的set方法,是將當前線程和Looper綁定到一塊兒:首先獲取到當前的線程,並獲取線程內部類Values,經過Thread.Values的put方法,將當前線程和Looper對象進行綁定到一塊兒。即將傳入的Looper對象掛載到當前線程上。

Tips:在Looper對象中,能夠經過getThread()方法,獲取到當前線程,即此Looper綁定的線程對象。

源代碼:

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));

    }

ThreadLocal中:

public void set(T value) {

        Thread currentThread = Thread.currentThread();

        Values values = values(currentThread);

        if (values == null) {

            values = initializeValues(currentThread);

        }

        values.put(this, value);

    }

2、建立消息Message

消息的建立能夠經過兩種方式:

1)new Message()

2)Message.obtain():【當存在多個handler的時候,能夠經過Message.obtain(Handler handler)建立消息,指定處理的handler對象】

Tips:建議使用第二種方式更好一些。緣由:

       由於經過第一種方式,每有一個新消息,都要進行new一個Message對象,這會建立出多個Message,很佔內存。

       而若是經過obtain的方法,是從消息池sPool中取出消息。每次調用obtain()方法的時候,先判斷消息池是否有消息(if (sPool != null)),沒有則建立新消息對象,有則從消息池中取出消息,並將取出的消息從池中移除【具體看obtain()方法】

public static Message obtain() {

        synchronized (sPoolSync) {

            if (sPool != null) {

                Message m = sPool;

                sPool = m.next;

                m.next = null;

                sPoolSize--;

                return m;

            }

        }

        return new Message();

    }

 

public Message() {

    }

3、建立Handler對象

兩種形式建立Handler對象:

1)建立無參構造函數的Handler對象:

2)建立指定Looper對象的Handler對象

最終都會調用相應的含有Callback和boolean類型的參數的構造函數

【這裏的Callback是控制是否分發消息的,其中含有一個返回值爲boolean的handleMessage(Message msg)方法進行判斷的;

  boolean類型的是參數是判斷是否進行異步處理,這個參數默認是系統處理的,咱們無需關心】

在這個構造函數中,進行了一系列的初始化工做:

①、獲取到當前線程中的Looper對象

②、經過Looper對象,獲取到消息隊列MessageQueue對象

③、獲取Callback回調對象

④、獲取異步處理的標記

源代碼:

①、建立無參構造函數的Handler對象:

public Handler() {

        this(null, false);

    }

public Handler(Callback callback, boolean async) {

        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 = callback;

        mAsynchronous = async;

    }

 

②、建立指定Looper對象的Handler對象

public Handler(Looper looper) {

        this(looper, null, false);

    }

public Handler(Looper looper, Callback callback, boolean async) {

        mLooper = looper;

        mQueue = looper.mQueue;

        mCallback = callback;

        mAsynchronous = async;

    }

 

4、Handler對象發送消息:

1)Handler發送消息給消息隊列:

Handler對象經過調用sendMessage(Message msg)方法,最終將消息發送給消息隊列進行處理

這個方法(全部重載的sendMessage)最終調用的是enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)

(1)先拿到消息隊列:在調用到sendMessageAtTime(Message msg, long uptimeMillis)方法的時候,獲取到消息隊列(在建立Handler對象時獲取到的)

(2)當消息隊列不爲null的時候(爲空直接返回false,告知調用者處理消息失敗),再調用處理消息入列的方法:

enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)

這個方法,作了三件事:

①、爲消息打上標籤:msg.target = this;:將當前的handler對象這個標籤貼到傳入的message對象上,爲Message指定處理者

②、異步處理消息:msg.setAsynchronous(true);,在asyn爲true的時候設置

③、將消息傳遞給消息隊列MessageQueue進行處理:queue.enqueueMessage(msg, uptimeMillis);

 

public final boolean sendMessage(Message msg){

        return sendMessageDelayed(msg, 0);

    }

public final boolean sendMessageDelayed(Message msg, long delayMillis){

        if (delayMillis < 0) {

            delayMillis = 0;

        }

        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);

    }

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);

    }

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {

        msg.target = this;

        if (mAsynchronous) {

            msg.setAsynchronous(true);

        }

        return queue.enqueueMessage(msg, uptimeMillis);

    }

 

2)MessageQueue消息隊列處理消息:

在其中的enqueueMessage(Message msg, long when)方法中,工做以下:

在消息未被處理且handler對象不爲null的時候,進行以下操做(同步代碼塊中執行)

①、將傳入的處理消息的時間when(即爲上面的uptimeMillis)賦值爲當前消息的when屬性。

②、將next()方法中處理好的消息賦值給新的消息引用:Message p = mMessages;

       在next()方法中:不斷的從消息池中取出消息,賦值給mMessage,當沒有消息發來的時候,Looper的loop()方法因爲是阻塞式的,就一直等消息傳進來

③、當傳入的時間爲0,且next()方法中取出的消息爲null的時候,將傳入的消息msg入列,排列在消息隊列上,此時爲消息是先進先出的

       不然,進入到死循環中,不斷的將消息入列,根據消息的時刻(when)來排列發送過來的消息,此時消息是按時間的前後進行排列在消息隊列上的

final boolean enqueueMessage(Message msg, long when) {

        if (msg.isInUse()) {

            throw new AndroidRuntimeException(msg + " This message is already in use.");

        }

        if (msg.target == null) {

            throw new AndroidRuntimeException("Message must have a target.");

        }

        boolean needWake;

        synchronized (this) {

            if (mQuiting) {

                RuntimeException e = new RuntimeException(msg.target + " sending message to a Handler on a dead thread");

                Log.w("MessageQueue", e.getMessage(), e);

                return false;

            }

 

            msg.when = when;

            Message p = mMessages;

            if (p == null || when == 0 || when < p.when) {

                // New head, wake up the event queue if blocked.

                msg.next = p;

                mMessages = msg;

                needWake = mBlocked;

            } else {

                needWake = mBlocked && p.target == null && msg.isAsynchronous();

                Message prev;

                for (;;) {

                    prev = p;

                    p = p.next;

                    if (p == null || when < p.when) {

                        break;

                    }

                    if (needWake && p.isAsynchronous()) {

                        needWake = false;

                    }

                }

                msg.next = p; // invariant: p == prev.next

                prev.next = msg;

            }

        }

        if (needWake) {

            nativeWake(mPtr);

        }

        return true;

    }

 

5、輪詢Message

1)開啓loop輪詢消息

當開啓線程的時候,執行run方法,在HandlerThread類中,調用的run方法中將開啓loop進行輪詢消息隊列:

在loop方法中,先拿到MessageQueue對象,而後死循環不斷從隊列中取出消息,當消息不爲null的時候,經過handler分發消息:msg.target.dispatchMessage(msg)。消息分發完以後,調用msg.recycle()回收消息,

2)回收消息:

在Message的回收消息recycle()這個方法中:首先調用clearForRecycle()方法,將消息的全部字段都恢復到原始狀態【如flags=0,what=0,obj=null,when=0等等】

而後在同步代碼塊中將消息放回到消息池sPool中,從新利用Message對象

源代碼:

Looper.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;

        Binder.clearCallingIdentity();

        final long ident = Binder.clearCallingIdentity();

        for (;;) {

            Message msg = queue.next(); // might block

            if (msg == null) {

               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);

            }

            final long newIdent = Binder.clearCallingIdentity();

            if (ident != newIdent) {

                Log.wtf(TAG, 「……」);

            }

            msg.recycle();

        }

    }

 

msg.recycle();

public void recycle() {

        clearForRecycle();

        synchronized (sPoolSync) {

            if (sPoolSize < MAX_POOL_SIZE) {

                next = sPool;

                sPool = this;

                sPoolSize++;

            }

        }

    }

 

/*package*/ void clearForRecycle() {

        flags = 0;

        what = 0;

        arg1 = 0;

        arg2 = 0;

        obj = null;

        replyTo = null;

        when = 0;

        target = null;

        callback = null;

        data = null;

    }

 

六、處理Message

在Looper.loop()方法中調用了msg.target.dispatchMessage(msg);的方法,就是調用了Handler中的dispatchMessage(Message msg)方法:

1)依據Callback中的handleMessage(msg)的真假判斷是否要處理消息,若是是真則不進行消息分發,則不處理消息,不然進行處理消息

2)當Callback爲null或其handleMessage(msg)的返回值爲false的時候,進行分發消息,即調用handleMessage(msg)處理消息【這個方法須要本身複寫】

 

/**

     * Subclasses must implement this to receive messages.

     */

    public void handleMessage(Message msg) {

    }

   

    /**

     * 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);

        }

    }

 

==========

場景一:

在主線程中建立Handler,其中複寫了handlerMessager方法(處理message,更新界面)

而後建立子線程,其中建立Message對象,並設置消息,經過handler發送消息

示例代碼:

public class MainActivity2 extends Activity implements OnClickListener{

    private Button bt_send;

       private TextView tv_recieve;

       private Handler handler = new Handler(){

              @Override

              public void handleMessage(Message msg) {

                     super.handleMessage(msg);

                     tv_recieve.setText((String) msg.obj);

              }

       };

 

       @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        bt_send = (Button) findViewById(R.id.bt_send);

        tv_recieve = (TextView) findViewById(R.id.tv_recieve);

        bt_send.setOnClickListener(this);

        tv_recieve.setOnClickListener(this);

       }

       @Override

       public void onClick(View v) {

              switch (v.getId()) {

              case R.id.bt_send:

                     new Thread(){

                            public void run() {

                                   Message msg = new Message();

                                   msg.obj = "消息來了"+ System.currentTimeMillis();

                                   handler.sendMessage(msg);

                            }

                     }.start();

                     break;

              }

       }

}

執行過程:

一、Looper.prepare()

在當前線程(主線程)中準備一個Looper對象,即輪詢消息隊列MessageQueue的對象;此方法會建立一個Looper,在Looper的構造函數中,初始化的建立了一個MessageQueue對象(用於存放消息),並準備好了一個線程供調用

二、new Hnader():

在當前線程中建立出Handler,須要複寫其中的handleMessage(Message msg),對消息進行處理(更新UI)。在建立Handler中,會將Looper設置給handler,並隨帶着MessageQueue對象;其中Looper是經過調用其靜態方法myLooper(),返回的是ThreadLocal中的currentThread,並準備好了MessageQueue【mQueue】

三、Looper.loop():

無限循環,對消息隊列進行不斷的輪詢,若是沒有獲取到消息,就會結束循環;若是有消息,直接從消息隊列中取出消息,並經過調用msg.target.dispatchMessage(msg)進行分發消息給各個控件進行處理。

[其中的msg.target實際就是handler]。

四、建立子線程,handler.sendMessage(msg)

在handler.sendMessage(msg)方法中,實際上最終調用sendMessageAtTime(Message msg,long uptimeMillis)方法[sendMessageXXX方法都是最終調用的sendMessageAtTime方法];此方法返回的enqueueMessage(queue,msg,uptimeMillis),實際上返回的是MessageQueue中的enqueueMessage(msg,uptimeMillis),其中進行的操做時對存入的消息進行列隊,即根據接收到的消息的時間前後進行排列[使用的單鏈形式];而後將消息就都存入到了消息隊列中,等待着handler進行處理。

 

 

 

 

 

 

 

場景二:

建立兩個子線程,一個線程中建立Handler並進行處理消息,另外一個線程使用handler發送消息。

示例代碼:

public class MainActivity extends Activity implements OnClickListener{

 

   private Button bt_send;

       private TextView tv_recieve;

       private Handler handler;

 

       @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        bt_send = (Button) findViewById(R.id.bt_send);

        tv_recieve = (TextView) findViewById(R.id.tv_recieve);

        bt_send.setOnClickListener(this);

        tv_recieve.setOnClickListener(this);

        new Thread(){

               public void run() {

                      //Looper.prepare();

                      handler = new Handler(Looper.getMainLooper()){

                             @Override

                             public void handleMessage(Message msg) {

                                    super.handleMessage(msg);

                                    tv_recieve.setText((String) msg.obj);

                                   

                             }

                      };

                      //Looper.loop();

               }

        }.start();

    }

 

       @Override

       public void onClick(View v) {

              switch (v.getId()) {

              case R.id.bt_send:

                     new Thread(){

                            public void run() {

                                   Message msg = new Message();

                                   msg.obj = "消息來了"+ System.currentTimeMillis();

                                   handler.sendMessage(msg);

                            }

                     }.start();

                     break;

              }

       }

}

 

簡單說明執行過程:

說明:在子線程中是不能更新界面的操做的,只能放在主線程中進行更新。因此必須將處理的消息放到主線程中,才能進行更新界面,不然會報錯

一、子線程中建立Handler,並處理消息

1)建立Handler:

源碼以下:

public Handler(Looper looper, Callback callback, boolean async) {

  mLooper = looper;

  mQueue = looper.mQueue;

  mCallback = callback;

  mAsynchronous = async;

}

這個構造函數作了一下幾步工做:

①、建立輪詢器:

因爲新建立的子線程中沒有輪詢器,就須要建立一個輪詢器,才能進行消息的輪詢處理。傳入的是主線程的輪詢器,就已經將這個looper綁定到主線程上了【傳入哪一個線程的Looper,就綁定在哪一個線程上】

②、將消息隊列加入到輪詢器上。

消息隊列MessageQueue是存放handler發來的消息的,等着Looper進行輪詢獲取;在一個線程中的MessageQueue須要一個Looper進行管理,因此二者須要同在一個線程中。

③、回調和異步加載。(此處不作分析[其實我還沒分析好])

須要注意的是界面更新:

上面說到了,在子線程中是不能夠進行更新界面的操做的,這就須要使用帶有輪詢器參數的handler構造函數進行建立,傳入主線程的輪詢器:Looper.getMainLooper(),從而將消息加入到主線程的消息隊列之中。所以就可進行在handleMessage方法中進行處理消息更新界面了。

2)、消息處理:

複寫其中的handleMessage(Message msg),對消息進行處理(更新UI)。在建立Handler中,會將Looper設置給handler,並隨帶着MessageQueue對象;其中Looper是經過調用其靜態方法myLooper(),返回的是ThreadLocal中的currentThread,並準備好了MessageQueue【mQueue】

雖然是在子線程中編寫的代碼,可是因爲傳入的是主線程的looper,因此,Looper從MessageQueue隊列中輪詢獲取消息、再進行更新界面的操做都是在主線程中執行的。

3)、Looper.loop():

說明:因爲傳入的是主線程的Looper,而在主線程中已經有這一步操做了,因此這裏就不須要進行顯示的調用了。可是主線程在這個時候是作了這個輪詢的操做的。

無限循環,對消息隊列進行不斷的輪詢,若是沒有獲取到消息,就會結束循環;若是有消息,直接從消息隊列中取出消息,並經過調用msg.target.dispatchMessage(msg)進行分發消息給各個控件進行處理。

[其中的msg.target實際就是handler]。

二、建立子線程,發送消息handler.sendMessage(msg)

新開一個子線程,發送消息給另外一個子線程

在handler.sendMessage(msg)方法中,實際上最終調用sendMessageAtTime(Message msg,long uptimeMillis)方法[sendMessageXXX方法都是最終調用的sendMessageAtTime方法]

此方法返回的enqueueMessage(queue,msg,uptimeMillis),實際上返回的是MessageQueue中的enqueueMessage(msg,uptimeMillis),其中進行的操做時對存入的消息進行列隊,即根據接收到的消息的時間前後進行排列[使用的單鏈形式];而後將消息就都存入到了消息隊列中,等待着handler進行處理。

 

 

dub本身總結:

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息