Android異步相關-Handler

Handler機制相關

Handler的幾個關鍵對象

Handler:Handler類幾個核心對象Lopper、MessageQueue、Callback、IMessager,很明顯Hadnler機制怎麼跑都在這裏了,後面再詳細看
Looper:幾個主要的對象:static Looper存儲了主線程的Looper;Thread存儲當前線程;MessageQueue當前線程隊列;還有一個static ThreadLocal<Looper>,這個ThreadLocal大概就是用來存儲的並且每個線程都只有一個互不干擾,所以這邊存儲跟取出的都是當前線程的Looper,詳細的自查
MessageQueue:消息隊列
Message:消息體

先簡單來說下流程:Handler.sendMessage將Message加入MessageQueue消息隊列中,Looper.prepare會存儲當前線程的Looper到ThreadLocal中,Looper.loop從消息隊列MessageQueue中循環取出消息交給Handler處理,最後Handler會根據一定的規則派發這些消息

第一步:Handler.sendMessage
sendMessage->sendMessageDelayed->sendMessageAtTime->enqueueMessage

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}
 boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }

        synchronized (this) {
            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w(TAG, e.getMessage(), e);
                msg.recycle();
                return false;
            }

            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            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 {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                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;
            }

            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

這邊會將Message加入到消息隊列中
第二步:我們在子線程中會執行Looper.loop讓Handler跑起來

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
        final Printer logging = me.mLogging;
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }

        final long traceTag = me.mTraceTag;
        if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
            Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
        }
          //執行處理消息的回調
        try {
            msg.target.dispatchMessage(msg);
        } finally {
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }

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

loop()方法中有一個無限循環,不停地讀取調用MessageQueue的next()方法。當next()沒有返回時就阻塞在這裏。當獲取到MessageQueue中的消息時,就執行了處理消息的回調函數msg.target.dispatchMessage(msg)。注意,這裏的msg.target就是Handler了,每個Message都會存儲發送它的Handler。
第三步:Handler的處理

    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

這裏很簡單,就是Message.mCallback>Handler.Callback>handleMessage;如果Message有設置Callback則分發給它處理,優先級最高;如無則看Handler本身有沒有設置Callback有則分發給它處理,最後都沒人處理則調用handleMessage處理,也是我們最常用的處理方式

Handler與主線程

子線程默認是沒有消息隊列MessageQueue的,而主線程只不過是 系統爲我們做了這部分工作而已,相關代碼就在ActivityThread.main方法中 。ActivityThread保存一個Handler,並prepare爲我們創建了消息隊列MessageQueue同時將主線程的Looper以靜態的方式保存在Looper類中(開文有提到)。最後很容易發現主線程的各個生命週期的調用其實也是通過主線程的Handler的

public void handleMessage(Message msg) {
    ...
    switch (msg.what) {
        case LAUNCH_ACTIVITY: {
            ...
            handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        } break;
        ...
        case PAUSE_ACTIVITY: {
            ...
            handlePauseActivity((IBinder) args.arg1, false,
                    (args.argi1 & USER_LEAVING) != 0, args.argi2,
                    (args.argi1 & DONT_REPORT) != 0, args.argi3);
            ...
        } break;

        ...
        case SHOW_WINDOW:
            ...
            handleWindowVisibility((IBinder)msg.obj, true);
            ...
            break;
        ...
        case EXIT_APPLICATION:
            if (mInitialApplication != null) {
                mInitialApplication.onTerminate();
            }
            Looper.myLooper().quit();
            break;
        ...
    }
    ...
}

Handler雜

  • Message msg = Handler.obtainMessage(),獲取一個複用的Message
  • Handler h = new Handler(){handleMessage()}這樣容易出現內存泄漏,需要在onDestroy中清除handler的所有消息和回調(Activity調用onDestroy結束後,若還有消息handler將繼續持有Activity的引用,此無法被回收)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章