從零了解Android消息機制

本著深入淺出的原則,本文詳細介紹了從線程到Handler消息傳遞機制的內容,中間多引用博客,如果不了解,還是要詳細看下鏈接里面的內容,適合像我這種基礎不扎實的同學學習下。

首先,廢話下為什么要有異步任務:
如果在主線程(UI線程)操作一些耗時的操作容易造成卡頓,
Android 規定主線程中不可以做耗時操作(訪問網絡,操作數據庫)

現在最基礎的異步任務的使用方法:
1.使用Handler消息傳遞機制;
2.使用AsyncTask異步任務;

要是這時候你不熟悉實現多線程的方式,請狂點
java線程系列---Runnable和Thread的區別

結論:
實現方式是1.實現Runnable接口 2.繼承Thread類
多線程肯定永遠以實現Runnable接口為主
使用Runnable實現多線程可以達到資源共享目的
另外,Thread類也是Runnable親兒子

要是這時候你不能隨手寫出Handler的實現方式,請狂點
Android Handler詳細使用方法實例

用法:
1.將handler綁定到它所建立的線程中,簡單粗暴沒情趣

    //使用handler時首先要創建一個handler(UI線程)
    Handler handler = new Handler();

    //將線程接口立刻送到線程隊列中
    handler.removeCallbacks(update_thread);

    Runnable update_thread = new Runnable()
    {
        public void run()
        {
            //UI操作
        }
    };
    handler.post(update_thread);
    //將接口從線程隊列中移除

2.handler的消息隊列機制,慢條斯理前戲足

    // 調用:
    update_progress_handler.post(update_thread);

    //創建一個handler,內部完成處理消息方法
    Handler update_progress_handler = new Handler()
    {
        @Override
        public void handleMessage(Message msg) {
            // UI線程
            // msg.arg1 = "bilibili"
        }
    };

    Runnable update_thread = new Runnable()
    {
        public void run() {
            Message msg = update_progress_handler.obtainMessage();
            //把消息發送到消息隊列中,msg對應handleMessage的入參
            msg.arg1 = "bilibili";
            update_progress_handler.sendMessage(msg);
        }
    };

    //移除
    update_progress_handler.removeCallbacks(update_thread);

3.自己看鏈接吧...

handler.sendMessage(msg) 和 handler.post(Runnable) 都知道什么情況下用了,接下來就是硬菜了

請狂點:
Android 異步消息處理機制 讓你深入理解 Looper、Handler、Message三者關系

結論

1、首先Looper.prepare()在本線程中保存一個Looper實例,然后該實例中保存一個MessageQueue對象;因為Looper.prepare()在一個線程中只能調用一次,所以MessageQueue在一個線程中只會存在一個。
2、Looper.loop()會讓當前線程進入一個無限循環,不端從MessageQueue的實例中讀取消息,然后回調msg.target.dispatchMessage(msg)方法。
3、Handler的構造方法,會首先得到當前線程中保存的Looper實例,進而與Looper實例中的MessageQueue想關聯。
4、Handler的sendMessage方法,會給msg的target賦值為handler自身,然后加入MessageQueue中。
5、在構造Handler實例時,我們會重寫handleMessage方法,也就是msg.target.dispatchMessage(msg)最終調用的方法

還有需要注意的,因為最終調用的方法都是這個

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

分發消息流程:

當Message的msg.callback不為空時,則回調方法msg.callback.run();
當Handler的mCallback不為空時,則回調方法mCallback.handleMessage(msg);
最后調用Handler自身的回調方法handleMessage(),該方法默認為空,Handler子類通過覆寫該方法來完成具體的邏輯。

消息分發的優先級:

Message的回調方法:message.callback.run(),優先級最高;
Handler中Callback的回調方法:Handler.mCallback.handleMessage(msg),優先級僅次于1;
Handler的默認方法:Handler.handleMessage(msg),優先級最低。

對于很多情況下,消息分發后的處理方法是第3種情況,即Handler.handleMessage(),一般地往往通過覆寫該方法從而實現自己的業務邏輯。

懵懵懂懂是嘛?換個方向給你說一遍,補充下內容,能更好的了解整個過程
Android消息機制的原理剖析—閉環總結

結論

(a)MessageQueue和Looper:一對一關系,MessageQueue的創建后放置在Looper中。
(b)Looper和線程:一個線程只有一個,創建之后保存在ThreadLocal中,想要獲取ThreadLocal.get()即可。
(c)Handler和Looper:Handler創建時候,從ThreadLocal中獲取Looper,Handler變量指向這個Looper,Handler和Looper綁定。
(d)Message和Handler:Handler發送Message時候,Message的target屬性指向這個Handler,也是這個Handler來分發處理這個Message
(e)消息池:only one,所有線程共享。

現在Android的消息機制都玩的溜了,不過對于偶爾用到一次用到就要考慮什么異步消息處理機制,還要專門使用一個Handler來發送和接收消息,就好比每次哄好了好不容易脫光了衣服還要先洗澡一樣...

這個時候,就必須要學會AsyncTask了
Android AsyncTask完全解析,帶你從源碼的角度徹底理解

強突:

 * 執行次序    執行時機        方法名稱           調用方
 *  1        異步任務執行前   onPreExecute      UI線程
 *  2        異步任務執行中   doInBackground    后臺線程
 *  3        異步任務執行中   publishProgress   后臺線程
 *  4        異步任務執行中   onProgressUpdate    UI線程
 *  5        異步任務執行后   onPostExecute       UI線程

使用:

private class MyTask extends AsyncTask<String, Integer, String> {
        @Override
        protected void onPreExecute() {
            //onPreExecute方法用于在執行后臺任務前做一些UI操作
        }

        //doInBackground方法內部執行后臺任務,不可在此方法內修改UI
        @Override
        protected String doInBackground(String... params) {
            //doInBackground方法內部執行后臺任務,不可在此方法內修改UI
            // 后臺線程向UI線程發布進度狀態
            publishProgress(i);
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... progresses) {
            //onProgressUpdate方法用于更新進度信息
        }

        @Override
        protected void onPostExecute(String result) {
            //onPostExecute方法用于在執行完后臺任務后更新UI,顯示結果
        }

        @Override
        protected void onCancelled() {
            //onCancelled方法用于在取消執行中的任務時更改UI
        }
    }

調用:

               //注意每次需new一個實例,新建的任務只能執行一次,否則會出現異常
                mTask = new MyTask();
                mTask.execute();

                //取消一個正在執行的任務,onCancelled方法將會被調用
                mTask.cancel(true);

結論:

AsyncTask也是使用的異步消息處理機制,只是做了非常好的封裝

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,908評論 6 541
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,324評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,018評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,675評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,417評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,783評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,779評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,960評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,522評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,267評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,471評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,009評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,698評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,099評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,386評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,204評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,436評論 2 378

推薦閱讀更多精彩內容