Handler(四)--Looper

系列目錄: Handler機制原理

1.prepareMainLooper()

    //Looper#prepareMainLooper
    public static void prepareMainLooper() {
        // 設(shè)置不允許退出的Looper
        prepare(false);
        synchronized (Looper.class) {
            //將當前的Looper保存為Looper诽里。每個線程只允許執(zhí)行一次
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

2.prepare()

    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    //Looper#prepare
    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));
    }

boolean quitAllowed表示Looper是否允許退出尚胞,true就表示允許退出缸逃,對于false則表示Looper不允許退出
sThreadLocal的作用已在之前文章中做過解析,異步ThreadLocal

3. Looper()

    //Looper#Looper
    private Looper(boolean quitAllowed) {
        // 創(chuàng)建MessageQueue對象
        mQueue = new MessageQueue(quitAllowed);
        // 記錄當前線程
        mThread = Thread.currentThread();
    }

4. myLooper()

    //Looper#myLooper
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

sThreadLocal.get()是和prepare(boolean)方法里面的sThreadLocal.set(new Looper(quitAllowed))一一對應(yīng)的炉爆。

5. loop()

    //Looper#loop
    public static void loop() {
         // 獲取TLS存儲的Looper對象
        final Looper me = myLooper();
        //沒有Looper 對象榜配,直接拋異常
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        //獲取當前Looper對應(yīng)的消息隊列
        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();
        // 確保權(quán)限檢查基于本地進程,而不是基于最初調(diào)用進程
        final long ident = Binder.clearCallingIdentity();
        // 進入 loop的主循環(huán)方法
       // 一個死循環(huán)盖袭,不停的處理消息隊列中的消息,消息的獲取是通過MessageQueue的next()方法實現(xiàn)
        for (;;) {
             // 可能會阻塞
            Message msg = queue.next(); // might block
             // 如果沒有消息彼宠,則退出循環(huán)
            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
            // 默認為null鳄虱,可通過setMessageLogging()方法來指定輸出,用于debug功能
            Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }
           // 用于分發(fā)消息兵志,調(diào)用Message的target變量(也就是Handler了)的dispatchMessage方法來處理消息
            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.
            // 確保分發(fā)過程中identity不會損壞
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                // 打印identiy改變的log醇蝴,在分發(fā)消息過程中是不希望身份被改變
                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);
            }
            // 將Message放入消息池
            msg.recycleUnchecked();
        }
    }

loop進入循環(huán)模式宣肚,不斷重復(fù)下面的操作

  • 讀取MessageQueue的下一條Message
  • 把Message分發(fā)給相應(yīng)的target
  • 再把分發(fā)后的Message回到消息池想罕,以便重復(fù)利用

6. quit()

    //Looper#quit
    public void quit() {
        mQueue.quit(false);
    }

退出循環(huán)
將終止(loop()方法)而不處理消息隊列中的任何更多消息

7. quitSafely()

    //Looper#quitSafely
    public void quitSafely() {
        mQueue.quit(true);
    }

處理完MessageQueue內(nèi)當前的Messager列表后退出循環(huán)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市霉涨,隨后出現(xiàn)的幾起案子按价,更是在濱河造成了極大的恐慌,老刑警劉巖笙瑟,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件楼镐,死亡現(xiàn)場離奇詭異,居然都是意外死亡往枷,警方通過查閱死者的電腦和手機框产,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門凄杯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人秉宿,你說我怎么就攤上這事戒突。” “怎么了描睦?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵膊存,是天一觀的道長。 經(jīng)常有香客問我忱叭,道長隔崎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任韵丑,我火速辦了婚禮爵卒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘埂息。我一直安慰自己技潘,他們只是感情好,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布千康。 她就那樣靜靜地躺著享幽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拾弃。 梳的紋絲不亂的頭發(fā)上值桩,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機與錄音豪椿,去河邊找鬼奔坟。 笑死,一個胖子當著我的面吹牛搭盾,可吹牛的內(nèi)容都是我干的咳秉。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼鸯隅,長吁一口氣:“原來是場噩夢啊……” “哼澜建!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蝌以,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤炕舵,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后跟畅,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體咽筋,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年徊件,在試婚紗的時候發(fā)現(xiàn)自己被綠了奸攻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蒜危。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖睹耐,靈堂內(nèi)的尸體忽然破棺而出舰褪,到底是詐尸還是另有隱情,我是刑警寧澤疏橄,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布占拍,位于F島的核電站,受9級特大地震影響捎迫,放射性物質(zhì)發(fā)生泄漏晃酒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一窄绒、第九天 我趴在偏房一處隱蔽的房頂上張望贝次。 院中可真熱鬧,春花似錦彰导、人聲如沸蛔翅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽山析。三九已至,卻和暖如春掏父,著一層夾襖步出監(jiān)牢的瞬間笋轨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工赊淑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留爵政,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓陶缺,卻偏偏與公主長得像钾挟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子饱岸,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容