AsyncTask
封裝好的異步消息處理機制
屬于抽象類,需要創(chuàng)建子類繼承AsyncTask。
開啟子線程執(zhí)行耗時任務(wù),實現(xiàn)子線程和主線程之間的通信,完成主線程的UI更新操作。
優(yōu)點
- 方便實現(xiàn)異步通信
- 采用線程池的緩存線程和復(fù)用線程,避免頻繁創(chuàng)建銷毀線程帶來的系統(tǒng)資源開銷。
AsyncTask實現(xiàn)類
public abstract class AsyncTask<Params,Progress,Result>{
}
三個泛型參數(shù)的意義:
- Params:開始異步任務(wù)執(zhí)行時傳入給后臺的的參數(shù)類型。
- Progress:任務(wù)執(zhí)行過程中,下載進度顯示單位的數(shù)據(jù)類型。
- Result:異步任務(wù)執(zhí)行完成后,返回的結(jié)果類型。
常用方法
execute(Params param)
在主線程中觸發(fā)執(zhí)行異步線程任務(wù)。
onPreExecute()
在execute()錢自動調(diào)用,用處界面初始化操作,比如顯示一個進度條對話框。
doInBackground(Params params)
該方法內(nèi)所有代碼都在子線程中運行,處理耗時任務(wù),任務(wù)完成通過return語句將任務(wù)的執(zhí)行結(jié)果返回,如果AsyncTask
第三個泛型參數(shù)是Void,可以不返回任務(wù)執(zhí)行結(jié)果。該方法不可以進行UI操作。
onProgressUpdate(Progress values)
后臺任務(wù)調(diào)用publishProgress(Progress)方法后,該方法自動調(diào)用,在該方法內(nèi)可以對UI進行操作。
onPostExcute(Result result)
后臺任務(wù)執(zhí)行完畢并通過return語句進行返回是,該方法自動調(diào)用。利用返回的數(shù)據(jù)進行UI操作,比如提醒任務(wù)執(zhí)行的結(jié)果,關(guān)閉進度條對話框等。
onCancelled()
取消狀態(tài)并非真正的取消任務(wù),該方法執(zhí)行后,onPostExecute()方法就不會被調(diào)用。
定義子類
private class MyTask extends AsyncTask<Params, Progress, Result> {
@Override
protected void onPreExecute() {
//線程任務(wù)前的初始化操作
}
@Override
protected String doInBackground(String... params) {
// 自定義的線程任務(wù)
// 可調(diào)用publishProgress()顯示進度, 之后將執(zhí)行onProgressUpdate()
publishProgress(count);
}
@Override
protected void onProgressUpdate(Integer... progresses) {
// 在主線程 顯示線程任務(wù)執(zhí)行的進度
}
@Override
protected void onPostExecute(String result) {
// UI操作
}
@Override
protected void onCancelled() {
}
}
//創(chuàng)建實例
MyTask mTask = new MyTask();
//執(zhí)行任務(wù)
mTask.execute();
舉個例子
public class MainActivity extends AppCompatActivity{
private static String TAG = "MainActivity";
private TextView showText;
private Button startButton;
private Button cancelButton;
private ProgressBar progressBar;
private MyTask myTask = new MyTask();
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showText =(TextView)findViewById(R.id.text);
progressBar = (ProgressBar)findViewById(R.id.progress_bar);
startButton = (Button)findViewById(R.id.start_button);
startButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//同一個AsyncTask實例對象只能執(zhí)行1次,若執(zhí)行第2次將會拋出異常
myTask.execute();
}
});
cancelButton = (Button)findViewById(R.id.cancel_button);
cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
myTask.cancel(true);
}
});
}
private class MyTask extends AsyncTask<String,Integer,String> {
@Override
protected void onPreExecute(){
showText.setText("加載中");
}
@Override
protected String doInBackground(String...params){
try{
int count = 0 ;
int length = 1;
while(count<99){
count += length;
//調(diào)用publishProgress()顯示進度,之后執(zhí)行onProgressUpdate()
publishProgress(count);
Thread.sleep(50);
}
}catch(InterruptedException e){
e.printStackTrace();
}
return null;
}
// 主線程顯示執(zhí)行進度
@Override
protected void onProgressUpdate(Integer...progresses){
progressBar.setProgress(progresses[0]);
showText.setText("loading...."+progresses[0]+"%");
}
// 任務(wù)執(zhí)行結(jié)果
@Override
protected void onPostExecute(String result){
showText.setText("加載完成");
}
//取消加載
@Override
protected void onCancelled(){
showText.setText("取消加載");
progressBar.setProgress(0);
}
}
}
注意點
生命周期
結(jié)論
AsyncTask不與任何組件綁定生命周期
使用建議
在Activity 或 Fragment中使用 AsyncTask時,最好在Activity 或 Fragment的onDestory()調(diào)用 cancel(boolean);
內(nèi)存泄漏
結(jié)論
若AsyncTask被聲明為Activity的非靜態(tài)內(nèi)部類,當Activity需銷毀時,會因AsyncTask保留對Activity的引用 而導(dǎo)致Activity無法被回收,最終引起內(nèi)存泄露
使用建議
AsyncTask應(yīng)被聲明為Activity的靜態(tài)內(nèi)部類
線程任務(wù)執(zhí)行結(jié)果 丟失
結(jié)論
當Activity重新創(chuàng)建時(屏幕旋轉(zhuǎn) / Activity被意外銷毀時后恢復(fù)),之前運行的AsyncTask(非靜態(tài)的內(nèi)部類)持有的之前Activity引用已無效,故復(fù)寫的onPostExecute()將不生效,即無法更新UI操作
使用建議
在Activity恢復(fù)時的對應(yīng)方法 重啟 任務(wù)線程