在以下操做中都是基於UI主線程,在異步任務中使用Handler機制更新UI必須用new Handler();
來初始化。java
// 默認使用UI主線程的Looper Handler mHandler = new Handler(); mHandler.post(new Runnable(){});
在Android開發中常常會使用到線程,一想到線程,不少同窗就當即使用
new Thread(){...}.start();
這樣的方式。這樣若是在一個Activity中屢次調用上面的代碼,那麼將建立多個匿名線程,程序運行的越久可能會愈來愈慢。所以,須要一個Handler來啓動一個線程,以及刪除一個線程。
保證線程不會重複的建立。異步
特色:async
代碼示例:ide
// UI線程的Handler Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); // 處理UI更新 }; HandlerThread mBackThread = new HandlerThread("mybackthread"); mBackThread.start(); // 後臺線程的Handler Handler mBackHandler = new Handler(mBackThread.getLooper()); mBackHandler.post(new Runnable() { @Override public void run() { // 後臺線程執行耗時操做,異步 ... // mHandler發消息,回到主線程更新UI mHandler.sendMessage(msg); } });
注意:mBackHandler
的初始化必須在mBackThread.start();
以後,不然拿不到這個線程的looper。
這種模式經過mBackHandler.post(new Runnable() {})
來實現後臺異步任務執行,全部後臺任務都是經過HandlerThread
這個線程執行的,可是HandlerThread
是串行執行任務的,也就是每次post
後進入隊列排隊執行。
HandlerThread
的退出:oop
@Override protected void onDestroy() { super.onDestroy(); if(mBackThread != null){ mBackThread.quitSafely(); try { mBackThread.join(); mBackThread = null; mBackHandler = null; } catch (InterruptedException e) { e.printStackTrace(); } } }
查看源碼AsyncTask只是對Thread和Handler的一個封裝。post
AsyncTask <Params, Progress, Result>
Params
: 指定的是咱們傳遞給異步任務執行時的參數的類型Progress
: 指定的是咱們的異步任務在執行的時候將執行的進度返回給UI線程的參數的類型Result
: 指定的是異步任務執行完後返回給UI線程的結果的類型onPreExecute()
:UI Thread當中執行,這個方法是在執行異步任務以前的時候執行,咱們能夠在異步任務執行前作UI提示doInBackground(Params... params)
:這個方法就是來處理異步任務的方法,執行耗時操做。這個方法也是必需要實現的抽象方法。onProgressUpdate(Progess... values)
:UI Thread當中執行,用來更新進度條等onPostExecute(Result... result)
:UI Thread當中執行,當異步任務執行完以後,將doInBackground
結果返回給這個方法來更新UIexecute(Params... params)
executeOnExecutor(Executor exec, Params... params)
execute
默認執行方式不統一,1.5中順序執行,1.6到 2.3中並行執行,3.0之後又改回串行執行,並添加並行執行接口executeOnExecutor
execute
AsyncTask
對象只能被執行一次,即只能調用一次execute
,不然會拋出異常報錯Caused by: java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)
// 初始化AsyncTask及執行 protected void function() { ... // 串行執行,識別一張bitmap,每次執行前都須要從新new一個對象 mClassifierAsyncTask = new ClassifierAsyncTask(); mClassifierAsyncTask.execute(bitmap); } // 自定義AsyncTask任務類,實現doInBackground private ClassifierAsyncTask mClassifierAsyncTask; private class ClassifierAsyncTask extends AsyncTask<Bitmap , Void, String >{ @Override protected void onPreExecute() { super.onPreExecute(); mTvResult.setText(getString(R.string.classifying)); } @Override protected String doInBackground(Bitmap... bitmaps) { if(mMyTfClassifier == null) { mMyTfClassifier = new MyTfClassifier(MainActivity.this); } String result = mMyTfClassifier.recognizeImage(bitmaps[0]); return result; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); mTvResult.setText(result); } }
Activity
屏幕旋轉或銷燬時,若是AsyncTask
沒有執行完畢就會存在內存泄露。特別是屏幕旋轉時AsyncTask
沒有執行完畢,會致使屏幕異常。ui