Handler Looper簡(jiǎn)略

一、消息循環(huán)過(guò)程
Android應(yīng)用程序進(jìn)程在啟動(dòng)的時(shí)候伟叛,會(huì)在進(jìn)程中加載ActivityThread類略就,并且執(zhí)行這個(gè)類的main函數(shù),應(yīng)用程序的消息循環(huán)過(guò)程就是在這個(gè)main函數(shù)里面實(shí)現(xiàn)的

public static void main(String[] args) {
        踢星。澳叉。。。成洗。五督。
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        。瓶殃。充包。。遥椿。基矮。
        Looper.loop();
    }

首先看Looper.prepareMainLooper函數(shù)

    // sThreadLocal.get() will return null unless you've called prepare().
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    final MessageQueue mQueue;
    final Thread mThread;

    public static void prepareMainLooper() {
        prepare(false);標(biāo)注1
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();標(biāo)注2
        }
    }

    標(biāo)注1: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));標(biāo)注3
    }

    標(biāo)注3:private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

    標(biāo)注2:public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

然后看Looper.loop()函數(shù):

    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;標(biāo)注4
        ......
        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            ......
            msg.target.dispatchMessage(msg);標(biāo)注5
            ......
            msg.recycleUnchecked();標(biāo)注6
        }
    }

標(biāo)注4:MessageQueue對(duì)象Message隊(duì)列
標(biāo)注5:Message的target是Handler
標(biāo)注6:回收Message

二、消息發(fā)送過(guò)程
ActivityManagerService通過(guò)調(diào)用ApplicationThread類的scheduleLaunchActivity函數(shù)通知應(yīng)用程序冠场,它可以加載應(yīng)用程序的默認(rèn)Activity了(ApplicationThread是ActivityThread的內(nèi)部類)

    private class ApplicationThread extends ApplicationThreadNative {
    @Override
        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            r.persistentState = persistentState;

            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;

            r.startsNotResumed = notResumed;
            r.isForward = isForward;

            r.profilerInfo = profilerInfo;

            r.overrideConfig = overrideConfig;
            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }
    }

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

mH是Handler愈捅,Handler.sendMessage最終會(huì)調(diào)用sendMessageAtTime方法:

    final MessageQueue mQueue;

    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;標(biāo)注7
        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);標(biāo)注8
    }

    public Handler(Callback callback, boolean async) {
        mLooper = Looper.myLooper();
        ......
        標(biāo)注7:mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

標(biāo)注8:private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;標(biāo)注9:Handler發(fā)送的Message中的target都是Handler本身
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);標(biāo)注10
    }

標(biāo)注9:Handler發(fā)送的Message中的target都是Handler本身
標(biāo)注10:MessageQueue的enqueueMessage方法就已經(jīng)將Message信息加入到消息隊(duì)列中了

三、消息的處理
在標(biāo)注5處獲取Message的target也就是當(dāng)前Handler(mH)對(duì)象慈鸠,調(diào)用Handler的dispatchMessage方法蓝谨,最終會(huì)調(diào)用mH的handlerMessage方法:

public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市青团,隨后出現(xiàn)的幾起案子譬巫,更是在濱河造成了極大的恐慌,老刑警劉巖督笆,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件芦昔,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡娃肿,警方通過(guò)查閱死者的電腦和手機(jī)咕缎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)料扰,“玉大人凭豪,你說(shuō)我怎么就攤上這事∩硅荆” “怎么了嫂伞?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)拯钻。 經(jīng)常有香客問我帖努,道長(zhǎng),這世上最難降的妖魔是什么粪般? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任拼余,我火速辦了婚禮,結(jié)果婚禮上亩歹,老公的妹妹穿的比我還像新娘匙监。我一直安慰自己凡橱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布舅柜。 她就那樣靜靜地躺著梭纹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪致份。 梳的紋絲不亂的頭發(fā)上变抽,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音氮块,去河邊找鬼绍载。 笑死,一個(gè)胖子當(dāng)著我的面吹牛滔蝉,可吹牛的內(nèi)容都是我干的击儡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼蝠引,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼阳谍!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起螃概,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤矫夯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后吊洼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體训貌,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年冒窍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了递沪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡综液,死狀恐怖款慨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情意乓,我是刑警寧澤樱调,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站届良,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏圣猎。R本人自食惡果不足惜士葫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望送悔。 院中可真熱鬧慢显,春花似錦爪模、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至应狱,卻和暖如春共郭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背疾呻。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工除嘹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人岸蜗。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓尉咕,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親璃岳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子年缎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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