異步消息處理線程啟動后會進入一個無限的循環(huán)體之中,每循環(huán)一次,從其內(nèi)部的消息隊列中取出一個消息,然后回調(diào)相應的消息處理函數(shù),執(zhí)行完成一個消息后則繼續(xù)循環(huán)。若消息隊列為空,線程則會阻塞等待。
一、使用的優(yōu)點:
結構清晰,功能定義明確 對于多個后臺任務時,簡單,清晰 使用的缺點:在單個后臺異步處理時,顯得代碼過多,結構過于復雜(相對性)
二、Handler 、 Looper 、Message 這三者的關系總結:1、首先Looper.PRepare()在本線程中保存一個Looper實例,然后該實例中保存一個MessageQueue對象;因為Looper.prepare()在一個線程中只能調(diào)用一次,所以MessageQueue在一個線程中只會存在一個。2、Looper.loop()會讓當前線程進入一個無限循環(huán),不端從MessageQueue的實例中讀取消息,然后回調(diào)msg.target.dispatchMessage(msg)方法。3、Handler的構造方法,會首先得到當前線程中保存的Looper實例,進而與Looper實例中的MessageQueue想關聯(lián)。4、Handler的sendMessage方法,會給msg的target賦值為handler自身,然后加入MessageQueue中。5、在構造Handler實例時,我們會重寫handleMessage方法,也就是msg.target.dispatchMessage(msg)最終調(diào)用的方法。好了,總結完成,大家可能還會問,那么在Activity中,我們并沒有顯示的調(diào)用Looper.prepare()和Looper.loop()方法,為啥Handler可以成功創(chuàng)建呢,這是因為在Activity的啟動代碼中,已經(jīng)在當前UI線程調(diào)用了Looper.prepare()和Looper.loop()方法。
三、Looper主要作用: 與當前線程綁定,保證一個線程只會有一個Looper實例,同時一個Looper實例也只有一個MessageQueue。 loop()方法,不斷從MessageQueue中去取消息,交給消息的target屬性的dispatchMessage去處理。 private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mRun = true; mThread = Thread.currentThread(); } 在構造方法中,創(chuàng)建了一個MessageQueue(消息隊列)。 public static final void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(true)); } 這也就說明了Looper.prepare()方法不能被調(diào)用兩次,同時也保證了一個線程中只有一個Looper實例。
四、在子線程中創(chuàng)建handler:
其實Handler不僅可以更新UI,你完全可以在一個子線程中去創(chuàng)建一個Handler,然后使用這個handler實例在任何其他線程中發(fā)送消息,最終處理消息的代碼都會在你創(chuàng)建Handler實例的線程中運行。 new Thread(){ private Handler handler; public void run() { Looper.prepare(); handler = new Handler() { public void handleMessage(android.os.Message msg) { Log.e("TAG",Thread.currentThread().getName()); }; };
一、使用的優(yōu)點: 簡單,快捷 、過程可控 使用的缺點:在使用多個異步操作和并需要進行Ui變更時,就變得復雜起來.
二、主要方法介紹:
doInBackground(Params…) 后臺執(zhí)行,比較耗時的操作都可以放在這里。注意這里不能直接操作UI。此方法在后臺線程執(zhí)行,完成任務的主要工作,通常需要較長的時間。在執(zhí)行過程中可以調(diào)用publicProgress(Progress…)來更新任務的進度。 onPostExecute(Result) 相當于Handler 處理UI的方式,在這里面可以使用在doInBackground 得到的結果處理操作UI。 此方法在主線程執(zhí)行,任務執(zhí)行的結果作為此方法的參數(shù)返回 onProgressUpdate(Progress…) 可以使用進度條增加用戶體驗度。 此方法在主線程執(zhí)行,用于顯示任務執(zhí)行的進度。 onPreExecute() 這里是最終用戶調(diào)用Excute時的接口,當任務執(zhí)行之前開始調(diào)用此方法,可以在這里顯示進度對話框。 onCancelled() 用戶調(diào)用取消時,要做的操作
三、使用AsyncTask類,以下是幾條必須遵守的準則: Task的實例必須在UI thread中創(chuàng)建; execute方法必須在UI thread中調(diào)用; 不要手動的調(diào)用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)這幾個方法; 該task只能被執(zhí)行一次,否則多次調(diào)用時將會出現(xiàn)異常;
四、實例說明:
創(chuàng)建一個asynctask:
/** * 執(zhí)行的順序: *      onPreExecute() ---> doInBackground() ---> publishProgress() ---> onProgressUpdate() ....---> onPostExecute() * ...表示:publishProgress() ---> onProgressUpdate() */public class MyAsyncTask extends AsyncTask<Integer , Object , String>{    private TextView tv;    public MyAsyncTask(TextView textView){        Log.e(TAG , "調(diào)用到了構造函數(shù)");        this.tv = textView;    }    /**     * 這里的Integer參數(shù)對應AsyncTask中的第一個參數(shù)     * 這里的String返回值對應AsyncTask的第三個參數(shù)     * 該方法并不運行在UI線程當中,主要用于異步操作,所有在該方法中不能對UI當中的空間進行設置和修改     * 但是可以調(diào)用publishProgress方法觸發(fā)onProgressUpdate對UI進行操作     */    @Override    protected String doInBackground(Integer[] params) {        int i;        for (i = 0; i <= 100; i++) {            publishProgress(i); //會將這個值傳遞給onProgressUpdate()方法            SystemClock.sleep(1000);        }        Log.e(TAG , "調(diào)用到了doInBackground  i = " + i );        return i + "";    }    /**     * 這里是最終用戶調(diào)用Excute時的接口,當任務執(zhí)行之前開始調(diào)用此方法,可以在這里顯示進度對話框。     */    @Override    protected void onPreExecute() {        Log.e(TAG , "調(diào)用到了onPreExecute");        super.onPreExecute();        tv.setText("開始執(zhí)行異步操作了");    }    /**     * 這里的String參數(shù)對應AsyncTask中的第三個參數(shù)(也就是接收doInBackground的返回值)     * 在doInBackground方法執(zhí)行結束之后在運行,并且運行在UI線程當中 可以對UI空間進行設置     */    @Override    protected void onPostExecute(String result) {        Log.e(TAG , "調(diào)用到了onPostExecute result = " + result );        super.onPostExecute(result);        tv.setText(result);    }    /**     * 這里的Intege參數(shù)對應AsyncTask中的第二個參數(shù)     * 在doInBackground方法當中,,每次調(diào)用publishProgress方法都會觸發(fā)onProgressUpdate執(zhí)行     * onProgressUpdate是在UI線程中執(zhí)行,所有可以對UI空間進行操作     */    @Override    protected void onProgressUpdate(Object... values) {        Log.e(TAG , "調(diào)用到了onProgressUpdate value = " + values);        super.onProgressUpdate(values);        tv.setText(values[0] + "");    }}執(zhí)行異步操作:
MyAsyncTask task = new MyAsyncTask(tv_show);task.execute();
新聞熱點
疑難解答
圖片精選