訊息傳遞和非同步任務
安卓中在子線成中更新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)
五色令人目盲,五音令人耳聾,五味令人口爽,馳騁畋獵令人心發狂,難得之貨令人行妨。是以聖人 ,為腹不為目,故去彼取此。