Handler機制解析

Hanlder機制用於線程間通訊,一般用於子線程給主線程發送消息更新UIandroid

Handler 
Message的主要處理者,用於發送消息,接收處理消息 
Message 
消息,線程間通訊的數據單元 
MessageQueue 
消息隊列,用於存放消息,取出消息 
Looper 
循環器,Message和Handler的橋樑,循環取出MessageQueue的消息發送Handleride

須要注意幾點:oop

在建立Handler以前,須要調用Looper.prepare()方法,之因此日常使用未調用過,是由於android在程序啓動時幫咱們建立好了,具體代碼在activityThread中的main()方法中,post

public static void main(String[] args) {

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

        SamplingProfilerIntegration.start();

        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        EventLogger.setReporter(new EventLoggingReporter());

        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());

        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        Process.setArgV0("<pre-initialized>");

 

        Looper.prepareMainLooper();//在此調用的Looper.prepare()

 

        ActivityThread thread = new ActivityThread();

        thread.attach(false);

        if (sMainThreadHandler == null) {

            sMainThreadHandler = thread.getHandler();

        }

        if (false) {

            Looper.myLooper().setMessageLogging(new

                    LogPrinter(Log.DEBUG, "ActivityThread"));

        }   

        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

 

        Looper.loop();

 

        throw new RuntimeException("Main thread loop unexpectedly exited");

    }

 

所以咱們在子線程使用Handler的時候,須要調用Looper.prepare()方法ui

class LooperThread extends Thread { 

      public Handler mHandler; 

 

      public void run() { 

          Looper.prepare(); 

 

          mHandler = new Handler() { 

              public void handleMessage(Message msg) { 

                  // process incoming messages here 

              } 

          }; 

 

          Looper.loop(); 

      } 

  } 

 

調用Looper.prepare()方法後只能確保在建立Handler的時候不報錯,若是不調用Looper.loop()方法,則沒有任何效果,一樣,android在程序啓動時,已經爲咱們作好了這一步this

public static void main(String[] args) {

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

        SamplingProfilerIntegration.start();

        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        EventLogger.setReporter(new EventLoggingReporter());    

        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());

        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        Process.setArgV0("<pre-initialized>");

 

        Looper.prepareMainLooper();//在此調用的Looper.prepare()

 

        ActivityThread thread = new ActivityThread();

        thread.attach(false);

        if (sMainThreadHandler == null) {

            sMainThreadHandler = thread.getHandler();

        }

        if (false) {

            Looper.myLooper().setMessageLogging(new

                    LogPrinter(Log.DEBUG, "ActivityThread"));

        }

        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

 

        Looper.loop();//在此調用的Looper.loop()

 

        throw new RuntimeException("Main thread loop unexpectedly exited");

    }

 

Handler的工做原理spa

當咱們啓動程序的時候,android自動在ActivityThread中幫咱們建立了Looper.prepare()方法,建立了Looper對象. 
在調用Looper.prepare()方法時,會建立Looper對象,當前線程會將Looper的對象保存,而且在Looper構造方法中,建立MessageQueue對象,也就是說一個Looper一個MessageQueue線程

 

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

    }

 private Looper(boolean quitAllowed) {

        mQueue = new MessageQueue(quitAllowed);

        mThread = Thread.currentThread();

    }

 

Handler調用postMessage之類的方法,最後都會調用sendMessageAtTime()方法,其中有queue.equeueMessage(msg)方法,實際就是消息入列邏輯code

public boolean sendMessageAtTime(Message msg, long uptimeMillis){ 

    boolean sent = false; 

    MessageQueue queue = mQueue; 

    if (queue != null) { 

        msg.target = this; 

        //該方法爲將消息添加到MessageQueue

        sent = queue.enqueueMessage(msg, uptimeMillis); 

    } 

    else { 

        RuntimeException e = new RuntimeException( 

            this + " sendMessageAtTime() called with no mQueue"); 

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

    } 

    return sent; 

} 

final boolean enqueueMessage(Message msg, long when) { 

    if (msg.when != 0) { 

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

    } 

    if (msg.target == null && !mQuitAllowed) { 

        throw new RuntimeException("Main thread not allowed to quit"); 

    } 

    synchronized (this) {    10    9

        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; 

        } else if (msg.target == null) { 

            mQuiting = true; 

        } 

        //將消息的時間傳進來賦給Message

        msg.when = when; 

        Message p = mMessages;        0

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

            msg.next = p; 1

                //將要取出的消息

            mMessages = msg;    0

            this.notify(); 

        } else { 

            Message prev = null; 

            while (p != null && p.when <= when) { 

                prev = p; 

                p = p.next; 

            } 

            msg.next = prev.next; 

            prev.next = msg; 

            this.notify(); 

        } 

    } 

    return true; 

} 

 

由上面咱們能夠得知,其實MessageQueue並無用集合將消息存儲起來,而是mMessages對象表示當前待處理的消息,所謂的加入隊列其實就是將全部的消息按時間進行排序,具體的操做就是根據Message的時間,去調用msg.next。 
從消息取出消息隊列是經過Looper.loop(),其實是一個死循環,不斷調用MessageQueue.next方法,他其中的操做就是判斷當前是否有須要處理的消息,若是有,則取出來,將下個消息成爲mMessages,不然就進入阻塞狀態,一直等待新消息的加入。對象

public static final void loop() { 

    Looper me = myLooper(); 

    MessageQueue queue = me.mQueue; 

    while (true) { 

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

        if (msg != null) { 

            if (msg.target == null) { 

                return; 

            } 

            if (me.mLogging!= null) me.mLogging.println( 

                    ">>>>> Dispatching to " + msg.target + " " 

                    + msg.callback + ": " + msg.what 

                    ); 

            msg.target.dispatchMessage(msg); 

            if (me.mLogging!= null) me.mLogging.println( 

                    "<<<<< Finished to    " + msg.target + " " 

                    + msg.callback); 

            msg.recycle(); 

        } 

    } 

} 

 

在Looper.loop()方法中找到將要處理的消息後,會調用msg.target.disPatcheMessage()方法,msg.target就是Handler.也就是調用了Handler.disPatchMessage()方法,在這個方法中,會判斷mCallBack是否爲空,若是不爲空調用callback,若是爲空,則調用了handlerMessage()方法,至此整個消息處理完成

public void dispatchMessage(Message msg) { 

    if (msg.callback != null) { 

        handleCallback(msg); 

    } else { 

        if (mCallback != null) { 

            if (mCallback.handleMessage(msg)) { 

                return; 

            } 

        } 

        handleMessage(msg); 

    } 

} 

 

對於上條的mCallBack,是由於在建立Handler對象的時候能夠傳入一個CallBack對象,若是return true,下面的handlermessage就不會收到消息,反正則能收到消息

   

private Handler mHandler = new Handler(new Handler.Callback() {

        @Override

        public boolean handleMessage(Message msg) {

            //返回爲true則下面的handlerMessage不能收到消息

            //返回false則下面的hanlderMessage可以收到消息

            return false;

        }

    }){

        @Override

        public void handleMessage(Message msg) {

            super.handleMessage(msg);

        }

    };
相關文章
相關標籤/搜索