#Android 消息機制handler詳細攻略+源碼解析

#Android 消息機制handler詳細攻略+源碼解析

Android 消息機制handler快速攻略,相信讀者開發中都遇到過,Android建議不要在主線程中進行耗時操作,否則會導致程序無法響應即ANR.還有網絡訪問,我們需要從服務端拉取一些信息並將其顯示在UI上,這個時候必須在子線程中進行拉取工作,獲取數據完畢後又不能在子線程中直接訪問UI,如果沒有Handler,那麼我們的確沒有辦法將訪問的UI工作切換到主線程中去執行.因此,系統之所以提供Handler,主要原因就是爲了解決在子線程中無法訪問UI的矛盾.在這之前我們需要了解下面幾個知識點

  • 安卓線程安全問題: 如果多個線程併發的操作UI組件,是可能導致線程的安全問題出現(如果加上鎖機制,2缺點:一邏輯複雜化,二鎖機制降低UI訪問效率)

  • 解決線程安全: 安卓提供解決的機制,只允許在UI主線程做組件修改

  • 什麼是UI主線程: 應用第一次啓動時,系統默認啓動一條UI線程(也稱之爲:主線程),專門負責處理UI相關的event

  • 怎麼在新線程修改UI組件: 這時候就需要使用Android中提供的一種異步回調機制Handler

一 消息隊列(MessageQueue)的工作原理

消息隊列在Android中指的是MessageQueue,MessageQueue主要包含兩個操作:插入和讀取.讀取操作本很會伴隨着刪除操作,插入和讀取對應的方法分別爲恩enqueueMessage和next,其中enqueueMessage的作用是往消息隊列中插入一條消息,而next的作用是從消息隊列中取出一條消息並將其從消息隊列中移除.儘管MessageQueue叫消息隊列,但是它的內部實現並不是用的隊列,實際上它是通過一個單鏈表的數據結構來維護消息列表,單鏈表在插入和刪除上比較有優勢.

下面主要看一下它的enqueueMessage和next方法的實現
在這裏插入圖片描述
在這裏插入圖片描述
enqueueMessage的實現來看,他的主要才做其實就是單鏈表的插入操作.

下面是next主要邏輯如下所示
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
可以發現next方法是一個無限循環的方法,如果消息隊列中沒有消息,那麼next方法會一直阻塞在這裏.當有新消息到來時,next方法會返回這條消息並將其從單鏈表中移除.

二 Looper的工作原理

Looper在Android的消息機制中扮演着消息循環的角色,它會不停地從MessageQueue中查看是否有新消息,如果有新消息就會立刻處理,否則就一直阻塞在那裏.它的構造方法,會創建一個MessageQueue即消息隊列,然後將當期線程的對象保存起來

在這裏插入圖片描述
其次,通過Looper.prepare()即可爲當前線程創建一個Looper,接着通過Looper.loop()來開啓消息循環
在這裏插入圖片描述

Looper的loop方法的工作過程比較好理解,loop方法是一個死循環,唯一跳出循環的方式是MessageQueue的next方法返回了null.當Looper的quit方法被調用時,Looper就會調用MessageQueue的quite或者quitSafely方法來通知消息隊列退出,當消息隊列被標記爲退出狀態時,它的next方法就會返回null.也就是說,Looper必須退出,否則loop方法就會無限循環下去.

三 Handler的工作原理

Handler的工作主要包含消息的發送和接收過程.消息的發送可以通過post的系列方法以及send的系列方法來實現,post的系列方法最終是通過sed的一系列方法來實現的.
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述

從上面可以發現,Handler發送消息的過程僅僅是向消息隊列中插入了一條消息,MessageQueue的next方法就會返回這條消息給Looper,Looper收到消息後就開始處理了,最終消息由Looper交由Handler處理,即Handler的diapatchMessage方法會被調用,這是Handler就進入了處理消息的階段

Handler處理消息的過程可以歸納爲一個流程圖.

在這裏插入圖片描述

四 ThreadLocal的工作原理

這個ThreadLocal相信不少讀者很少接觸到,日常開發彙總用到ThreadLocal的地方較少,ThreadLocal是一個線程內部的數據存儲類,通過它可以在指定的線程中存儲數據,數據存儲後,只有在指定線程中獲取到存儲的數據,對於其他線程來說則無法獲取到數據.但是在某些特殊的場景下,通過ThreadLocal可以輕鬆地實現一些看起來很複雜的功能,在Android的源碼種有所體現,比如Looper,ActivityThread以及AMS中都用到了ThreadLocal.

五 例子:輪循器使用

上線項目用到地方舉例:
1,在一個教育學習項目中,作業的定時上報成績,把內存緩存中的學生成績上報
2,VR教學中控項目,實時刷新補抓VR狀態

核心代碼部分:

	public void init(){
 		//開始刷狀態數據
        mHandler.post(runnable);
  }

    //5秒
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            mHandler.postDelayed(runnable, 10 * 1000);
            Message message = new Message();
            message.what = 1;
            mHandler.sendMessage(message);
        }
    };


    public Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 1:
                   //todo
                    break;
            }
        }
    };

//用完回收
   @Override
    public void onDestroy() {
        super.onDestroy();
	    mHandler.removeCallbacks(runnable);
    }

尾言

爲自己技術增值,量變引起質變.對象亦來源於生活,模式亦來源於驗證的OO經驗,那麼請學會使用輪子,再到感受制造輪子的樂趣,你會發現原來編程那麼美妙.如有錯誤或不當之處,請讀者留言,博主好吸取經驗,互相交流學習,如果本文對你有幫助請幫博主點贊,發注一波,謝謝善良的讀者

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章