1. 程式人生 > >Android 非同步訊息處理

Android 非同步訊息處理

前言

  • 我們都知道Android的UI執行緒是不安全,在子執行緒中更新UI會造成程式崩潰,但是我們有時候確實需要在子執行緒中進行耗時操作,然後再依據結果更新UI
  • 在學習具體的方法前我們首先看一下Android的非同步訊息處理機制示意圖

    這裡寫圖片描述

  • 我們再來把非同步訊息處理的整個流程梳理一下:

    1. 首先需要在主執行緒當中建立一個Handler物件,並重寫handleMessage()方法。
    2. 然後當子執行緒中需要進行UI操作時,就建立一個Message物件,並通過Handler將這條訊息傳送出去。
    3. 之後這條訊息會被新增到MessageQueue的佇列中等待被處理
    4. 而Looper則會一直嘗試從MessageQueue中取出待處理訊息,最後分發回Handler的handlerMessage()方法中。

方法總結

1.使用Handler

在主執行緒中建立Handler:

        public android.os.Handler handler=new android.os.Handler(){
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what){
                    case UPDATE_TEXT:
                        textView.setText(msg.obj.toString());
                        break;
                    default:
                        break;
                }
            }
        };

在子執行緒中呼叫sendMessage方法更新UI
注意:這裡的sendHttpRequest是OkHttp提供的回撥介面,是在子執行緒中執行的

      HttpUtil.sendHttpRequest(address,new okhttp3.Callback(){
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    String responseData = response.body().string();
                    Message message = new Message();
                    message.what=UPDATE_TEXT;
                    message.obj=responseData;
                    handler.sendMessage(message);
                }

                @Override
                public void onFailure(Call call, IOException e) {
                    e.printStackTrace();
                }
            });

2.使用runInUiThread()方法

  • 這表面看起來是一個很簡單的方法,但其實它就是一個非同步訊息處理機制的介面封裝,背後的實現原理其實和上圖的描述是一樣的。

    private void showResponse(final String response){
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                textView.setText(response);
            }
        });
    }
    

3.使用AsyncTask

  • 這種方法看起來需要編寫更多的程式碼,但是實際上在語義方面會更加清晰

            @Override
            protected void onPreExecute() {
                //這個方法會在後臺任務開始執行之前呼叫,用於進行一個介面上的初始化操作
                super.onPreExecute();
            }
    
            @Override
            protected Object doInBackground(Object[] params) {
                //這個方法中的所有程式碼都會在子執行緒中執行,我們應該在這裡去處理所有的耗時任務。
                //任務一旦完成就可以通過return語句來將任務的執行結果返回。
                //注意:在這個方法中是不可以進行UI操作的。
                return null;
            }
    
            @Override
            protected void onProgressUpdate(Object[] values) {
                 //當呼叫publishProgress()方法傳入當前的下載進度時。
                 //onProgressUpdate()方法就會很快被呼叫,在這裡就可以就行UI操作了
                super.onProgressUpdate(values);
            }
    
            @Override
            protected void onPostExecute(Object o) {
                //當doInBackground()方法返回時,onPostExecute()方法就會很快的被呼叫
                //執行一些任務的收尾工作
                super.onPostExecute(o);
            }
    

後記

  • 查資料時發現還有view.post方法,但是在這次實驗中並沒有用到,以後再接著補充
  • 這幾篇文章是我學習的時候看過的,上述這篇文章也是對這幾篇文章的總結加上自己的一點小感悟寫出來的。
  • 同時這幾篇文章中還有涉及到內部原始碼分析的,目前自己寫的只是將如何用寫出來而已。有時間的時候再深入學習更新記錄