1. 程式人生 > >訊息傳遞和非同步任務

訊息傳遞和非同步任務

安卓中在子線成中更新UI會出現錯誤,為了確保UI顯示的正確性,必須統一管理這些更改指令。怎麼把子執行緒中的指令傳遞到主執行緒UI中,安卓提供了Handler訊息機制。

handler message

void handleMessage(Message msg) handler中的訊息處理方法,根據訊息的不同做出不同的操作,一般被重寫,自己定義訊息的內容和操作內容。

final boolean hasMessage(int what)檢查訊息佇列中是否有該訊息。

Message obtainMessage()重用訊息佇列中的訊息,第一次會生成一個新的例項。

sendEmptyMessage()傳送一個空訊息,起始內部還是傳送的重用的Message物件,但是並沒有指定message的其他內容。

final boolean sendMessge(Message msg)傳送一個訊息

final boolean sendMessage (Message msg ,long delayMillis)延遲傳送message。

其實發送訊息只是把他們放在了MessageQueue中,訊息獲取是Looper的事情。
在Looper的loop方法中有一個無限迴圈的程式碼塊,他負責不停的從訊息隊列出取出訊息。然後交給相應的handler進行處理。

//繼承Handler 重寫 handlerMessage方法 自定義對訊息的處理方式
    class MyHandler extends  Handler
{
@Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ //根據自己傳進來的訊息的變數來識別訊息種類 不一定用msg.what } } } new Thread(new Runnable() { @Override public void run() { //需要處理的操作
//處理完成之後handler傳送訊息到MessageQueue中 Message msg=handler.obtainMessage(); msg.what=1; myHandler.sendMessage(msg) } }).start(); Message類中一般使用的變數。可以完全把他當成一個簡單型別來使用。 public int what; public int arg1; public int arg2; public Object obj;

一個執行緒內有一個訊息佇列,一個Looper,可以由多個handler和多個訊息。

非同步任務AsyncTask

***public abstract class AsyncTask<Params, Progress, Result> 是一個抽象類,params啟動任務時候需要傳入的引數,progress後臺完成任務進度值的型別,result執行任務完成返回值的型別。***

幾個主要方法
- doInBackGround(Params…)在後臺執行的任務,好比handler系列中子執行緒內的執行體。
- onProgressUpdate(Progress…)在主執行緒中執行,相當於handler中handleMessage(msg),比如在方法內設定textView.setText(“文字”)。
- publishProgress(Progress…)完成或完成部分內容向主執行緒傳送訊息,相當於handler.sendMessage()。
- onPreExecute 在執行後臺操作前呼叫,做準備工作,比如頁面顯示進度條等等。
- onPostExecute(result )當執行緒完成後(doInBackground完成後)自動呼叫,通知主執行緒完成。相當於最後一次publishProgress和onProgressUpdate的結合體。

  • execute(params…)我們能夠呼叫的方法。引數是我們需要傳入執行緒的內容,與類宣告是的型別保持一致。
//一個簡單的按鈕點選改變按鈕文字的示例 
//handler message 方法 設定監聽器 生成執行緒示例重寫run()方法,執行緒的執行體,線上程執行完畢後傳送訊息。
  mButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Message msg=myHandler.obtainMessage();
                    msg.what=1;
                    msg.obj="返回的文字資訊";
                    myHandler.sendMessage(msg);
                }
            }).start();
        }
    });
//handler接受到訊息進行識別處理。
    private  Handler myHandler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                //
                case 1:
                    mButton.setText(msg.obj.toString());
                    break;
            }
        }
    };
//AsyncTask  示例
//同樣設定監聽器 例項化 AsyncTask 啟動 
     mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                 myAsyncTask=new MyAsyncTask();
                  myAsyncTask.execute();
            }
        });
//自定義的AsyncTask 因為只是簡單任務 所以有些方法可以補充重寫
    class MyAsyncTask extends AsyncTask<Void,Integer ,String >{
        @Override
        protected String doInBackground(Void... voids) {
            //後臺任務執行體
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //一次 或多次向主執行緒傳遞訊息
            publishProgress(100);
            return "返回的文字資訊";
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            //簡單任務,不需要前置操作。
        }

        @Override
        protected void onPostExecute(String String) {
            super.onPostExecute(String);
            //操作完成後 UI操作
            mButton.setText(String);
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            //UI操作 耗時任務 進度型任務完成進度

        }
}

注意事項:

 1.必須在UI執行緒中建立AsyncTask例項。
 2.必須在UI執行緒中呼叫exectue()方法。
 3.重寫的執行任務的方法,有系統負責,我們只需要呼叫execute方法。
 4.每個AsyncTask只能執行一次。

MARK(12)

五色令人目盲,五音令人耳聾,五味令人口爽,馳騁畋獵令人心發狂,難得之貨令人行妨。是以聖人 ,為腹不為目,故去彼取此。