1、對於耗時的操作,我們的一般方法是開啓“子線程”。如果需要更新UI,則需要使用handler
2、如果耗時的操作太多,那麼我們需要開啓太多的子線程,這就會給系統帶來巨大的負擔,隨之也會帶來性能方面的問題。在這種情況下我們就可以考慮使用類AsyncTask來異步執行任務,不需要子線程和handler,就可以完成異步操作和刷新UI。
3、AsyncTask:對線程間的通訊做了包裝,是後臺線程和UI線程可以簡易通訊:後臺線程執行異步任務,將result告知UI線程。
4、使用方法:共分爲兩步,自定義AsyncTask,在耗時的地方調用自定義的AsyncTask。可以參照以下代碼示例。
step1:繼承AsyncTask<Params,Progress,Result>
Params:輸入參數。對應的是調用自定義的AsyncTask的類中調用excute()方法中傳遞的參數。如果不需要傳遞參數,則直接設爲Void即可。
Progress:子線程執行的百分比
Result:返回值類型。和doInBackground()方法的返回值類型保持一致。
step2:實現以下幾個方法:執行時機和作用看示例代碼,以下對返回值類型和參數進行說明
onPreExecute():無返回值類型。不傳參數
doInBackground(Params... params):返回值類型和Result保持一致。參數:若無就傳遞Void;若有,就可用Params
publishProgress(Params... params):在執行此方法的時候會直接調用onProgressUpdate(Params... values)
onProgressUpdate(Params... values):無返回值類型。參數:若無就傳遞Void;若有,就可用Progress
onPostExecute(Result result) :無返回值類型。參數:和Result保持一致。
step3:在調用自定義的AsyncTask類中生成對象;
執行 :對象.excute(Params... params);
小注:
AsyncTask主要方法的梳理:
執行次序 | 執行時機 | 方法名稱 | 調用方 |
1 | 異步任務執行前 | onPreExecute | UI線程 |
2 | 異步任務執行中 | doInBackground | 後臺線程 |
3 | 異步任務執行中 | publishProgress | 後臺線程 |
4 | 異步任務執行中 | onProgressUpdate | UI線程 |
5 | 異步任務執行後 | onPostExecute | UI線程 |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello"/>
<Button
android:id="@+id/download"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Download"/>
<TextView
android:id="@+id/tv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="當前進度顯示"/>
<ProgressBar
android:id="@+id/pb"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyleHorizontal"/>
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
public class AsyncTaskDemoActivity extends Activity {
/** Called when the activity is first created. */
private Button download;
private TextView tv;
private ProgressBar pb;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout1);
initView();
}
private void initView() {
// TODO Auto-generated method stub
tv=(TextView)findViewById(R.id.tv);
pb=(ProgressBar)findViewById(R.id.pb);
download=(Button)findViewById(R.id.download);
download.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
DownloadTask dt=new DownloadTask(AsyncTaskDemoActivity.this,pb,tv);
dt.execute(100);//參數影響線程的休息時間
}
});
}
import android.util.Log;
import android.widget.ProgressBar;
import android.widget.TextView;
public class DownloadAsyncTask extends AsyncTask<Integer, Integer, String> {
//後面尖括號內分別是參數(線程休息時間),進度(publishProgress用到),返回值 類型
private Context mContext=null;
private ProgressBar mProgressBar=null;
private TextView mTextView=null;
public DownloadAsyncTask(Context context, ProgressBar pb, TextView tv){
this.mContext=context;
this.mProgressBar=pb;
this.mTextView=tv;
}
/*
* 第一個執行的方法
* 執行時機:在執行實際的後臺操作前,被UI 線程調用
* 作用:可以在該方法中做一些準備工作,如在界面上顯示一個進度條,或者一些控件的實例化,這個方法可以不用實現。
* @see android.os.AsyncTask#onPreExecute()
*/
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
Log.d("DownloadAsyncTask", "onPreExecute executed");
super.onPreExecute();
}
/*
* 執行時機:在onPreExecute 方法執行後馬上執行,該方法運行在後臺線程中
* 作用:主要負責執行那些很耗時的後臺處理工作。可以調用 publishProgress方法來更新實時的任務進度。該方法是抽象方法,子類必須實現。
* @see android.os.AsyncTask#doInBackground(Params[])
*/
@Override
protected String doInBackground(Integer... params) {
// TODO Auto-generated method stub
Log.d("DownloadAsyncTask", "doInBackground executed");
for(int i=0;i<=100;i++){
publishProgress(i);//當前任務進度通過i傳入
try {
Thread.sleep(params[0]);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return "執行完畢";
}
/*
* 執行時機:這個函數在doInBackground調用publishProgress時被調用後,UI 線程將調用這個方法.雖然此方法只有一個參數,但此參數是一個數組,可以用values[i]來調用
* 作用:在界面上展示任務的進展情況,例如通過一個進度條進行展示。此實例中,該方法會被執行100次
* @see android.os.AsyncTask#onProgressUpdate(Progress[])
*/
@Override
protected void onProgressUpdate(Integer... values) {
int progress = values[0];
// TODO Auto-generated method stub
Log.d("DownloadAsyncTask", "onProgressUpdate executed");
mProgressBar.setProgress(progress);
mTextView.setText(values[0]+"%");
super.onProgressUpdate(values);
}
/*
* 執行時機:在doInBackground 執行完成後,將被UI 線程調用
* 作用:後臺的計算結果將通過該方法傳遞到UI 線程,並且在界面上展示給用戶
* result:上面doInBackground執行後的返回值,所以這裏是"執行完畢"
* @see android.os.AsyncTask#onPostExecute(java.lang.Object)
*/
@Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
Log.d("DownloadAsyncTask", "onPostExecute executed");
super.onPostExecute(result);