Handler消息機制

在Android中 整個系統(tǒng)的“消息機制” “事件傳遞” “反饋機制”就是由Handler來進行統(tǒng)一管理的


作用:
為了避免ANR卷员,我們會通常把 耗時操作放在子線程里面去執(zhí)行绍妨,因為子線程不能更新UI,所以當子線程需要更新的UI的時候就需要借助到安卓的消息機制懈叹,也就是Handler機制了。

  1. 我們先從Android的啟動類AcitvityThread的main函數(shù)看起


  2. 我們繼續(xù)深入 Looper.loop();


    msg.recycleUnchecked();//這里消息處理完成后 就進行回收
    
  3. 進入msg.target.dispatchMessage(msg);看看Handler是怎么處理消息的
public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }
- 如果msg.callback != null 那么這個callback代表什么呢
public final class Message implements Parcelable {
Runnable callback;//callback代表著一個Runnable
}
//在看看Handler的 handleCallback(msg);就明白
private static void handleCallback(Message message) {
        message.callback.run();//這里的run()就是一個回調(diào) 千萬別認為在分線程中執(zhí)行
    }
- 根據(jù)以上分析一目了然 我們平時這樣寫的代碼:
//寫法一
new Handler().post(new Runnable() {
            @Override
            public void run() {//在Hnadler在主線程的時候 run()也在主線程中執(zhí)行
                //這里就不用Handler去處理 而是你自己在run()回調(diào)里面處理
            }
        });
//寫法二
Runnable runnable=new Runnable() {
            @Override
            public void run() {
                //xxxxxx
            }
        };
 new Handler().postDelayed(runnable,1000);
  1. 分析完handleCallback(msg); 再接著往下走:
public void dispatchMessage(Message msg) {
     if (msg.callback != null) {
         handleCallback(msg);
     } else {
         if (mCallback != null) {//mCallback是Handler中定義的一個回調(diào)接口
             if (mCallback.handleMessage(msg)) {//執(zhí)行回調(diào)方法
                 return;
             }
         }
         handleMessage(msg);//若以上都為空 則執(zhí)行Handler的handleMessage()方法
     }
 }
- Handler.Callback
public class Handler {
         final Callback mCallback;//接口
         public interface Callback {
         public boolean handleMessage(Message msg);
         }
         public void handleMessage(Message msg) { }
}
- 平時代碼寫法:
private Handler handler=new Handler(new Handler.Callback() {
        //這里就給Handler的Callback賦值并回調(diào)
        @Override
        public boolean handleMessage(Message msg) {
            return false;
        }
    });
  1. 以上是分析了Handler怎么處理消息 再看Handler是如何發(fā)生消息的


public final boolean postAtTime(Runnable r, long uptimeMillis) {
        return sendMessageAtTime(getPostMessage(r), uptimeMillis);
    }
public final boolean post(Runnable r){
       return  sendMessageDelayed(getPostMessage(r), 0);
    }
//直接發(fā)送消息
public final boolean sendMessage(Message msg){
        return sendMessageDelayed(msg, 0);
    }
//發(fā)送空消息
public final boolean sendEmptyMessage(int what) {
        return sendEmptyMessageDelayed(what, 0);
    }
//發(fā)送延遲消息
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageDelayed(msg, delayMillis);
    }
//在某一時間點發(fā)送消息
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;
        }
      //這里將消息插入MessageQueue隊列中
        return enqueueMessage(queue, msg, uptimeMillis);
    }

由上得出 Handler不管是以哪種方式發(fā)送消息 最后都由sendMessageAtTime(msg, delayMillis)該方法來處理
--曾經(jīng)面試在這里躺坑了--

  1. 最后一些建議:
    • 創(chuàng)建Message對象的時候這樣創(chuàng)建:
Message message=Message.obtain();
//源碼:
/**
     * Return a new Message instance from the global pool. Allows us to
     * avoid allocating new objects in many cases.
     */
public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }
//通過注釋我們就知道這樣創(chuàng)建的Message是從消息池里面獲取的 避免重復(fù)創(chuàng)建對象;
  1. 分析了發(fā)送消息和處理消息 最后看看系統(tǒng)Handler做了哪些工作
public final class ActivityThread {
        final H mH = new H();
        private class H extends Handler {
         public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {//Activity---onStart()
                    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;
                case RELAUNCH_ACTIVITY: {//Activity--onRestart
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
                    handleRelaunchActivity(r);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     } break;
                case PAUSE_ACTIVITY://Activity--onPause
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
                            (msg.arg1&2) != 0);
                    maybeSnapshot();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    ..........................................//后面的代碼執(zhí)行觀看
        }
}

通過以上源碼發(fā)現(xiàn)Android四大組件的生命周期全部都是由Handler進行統(tǒng)一管理的 由此看出Handler在Android中的重要性典鸡。

**針對Looper是如何創(chuàng)建的 以及MessageQueue對Message的入隊和出隊是如何操作的 就放在下一篇文章講解 **

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市坏晦,隨后出現(xiàn)的幾起案子萝玷,更是在濱河造成了極大的恐慌嫁乘,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件球碉,死亡現(xiàn)場離奇詭異蜓斧,居然都是意外死亡,警方通過查閱死者的電腦和手機睁冬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門挎春,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人豆拨,你說我怎么就攤上這事直奋。” “怎么了施禾?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵脚线,是天一觀的道長。 經(jīng)常有香客問我弥搞,道長邮绿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任攀例,我火速辦了婚禮船逮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘肛度。我一直安慰自己傻唾,他們只是感情好,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布承耿。 她就那樣靜靜地躺著冠骄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪加袋。 梳的紋絲不亂的頭發(fā)上凛辣,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音职烧,去河邊找鬼扁誓。 笑死,一個胖子當著我的面吹牛蚀之,可吹牛的內(nèi)容都是我干的蝗敢。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼足删,長吁一口氣:“原來是場噩夢啊……” “哼寿谴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起失受,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤讶泰,失蹤者是張志新(化名)和其女友劉穎咏瑟,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體痪署,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡码泞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了狼犯。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片余寥。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖辜王,靈堂內(nèi)的尸體忽然破棺而出劈狐,到底是詐尸還是另有隱情,我是刑警寧澤呐馆,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布肥缔,位于F島的核電站,受9級特大地震影響汹来,放射性物質(zhì)發(fā)生泄漏续膳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一收班、第九天 我趴在偏房一處隱蔽的房頂上張望坟岔。 院中可真熱鬧,春花似錦摔桦、人聲如沸社付。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鸥咖。三九已至,卻和暖如春兄世,著一層夾襖步出監(jiān)牢的瞬間啼辣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工御滩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鸥拧,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓削解,卻偏偏與公主長得像富弦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子氛驮,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

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