轉 Android 多執行緒:手把手教你使用AsyncTask
阿新 • • 發佈:2020-11-30
轉自:https://www.jianshu.com/p/ee1342fcf5e7
前言
-
多執行緒的應用在Android開發中是非常常見的,常用方法主要有:
- 繼承Thread類
- 實現Runnable介面
- Handler
- AsyncTask
- HandlerThread
-
今天,我將獻上一份
AsyncTask
使用教程,希望大家會喜歡
目錄
示意圖1. 定義
- 一個
Android
已封裝好的輕量級非同步類 - 屬於抽象類,即使用時需 實現子類
public abstract class AsyncTask<Params, Progress, Result> {
...
}
2. 作用
- 實現多執行緒
在工作執行緒中執行任務,如 耗時任務 - 非同步通訊、訊息傳遞
實現工作執行緒 & 主執行緒(UI
執行緒)之間的通訊,即:將工作執行緒的執行結果傳遞給主執行緒,從而在主執行緒中執行相關的UI
操作
從而保證執行緒安全
3. 優點
- 方便實現非同步通訊
不需使用 “任務執行緒(如繼承Thread
類) +Handler
”的複雜組合 - 節省資源
採用執行緒池的快取執行緒 + 複用執行緒,避免了頻繁建立 & 銷燬執行緒所帶來的系統資源開銷
4. 類 & 方法介紹
4.1 類定義
AsyncTask
類屬於抽象類,即使用時需 實現子類
public abstract class AsyncTask<Params, Progress, Result> {
...
}
// 類中引數為3種泛型型別
// 整體作用:控制AsyncTask子類執行執行緒任務時各個階段的返回型別
// 具體說明:
// a. Params:開始非同步任務執行時傳入的引數型別,對應excute()中傳遞的引數
// b. Progress:非同步任務執行過程中,返回下載進度值的型別
// c. Result:非同步任務執行完成後,返回的結果型別,與doInBackground()的返回值型別保持一致
// 注:
// a. 使用時並不是所有型別都被使用
// b. 若無被使用,可用java.lang.Void型別代替
// c. 若有不同業務,需額外再寫1個AsyncTask的子類
}
4.2 核心方法
AsyncTask
核心 & 常用的方法如下:
- 方法執行順序如下
5. 使用步驟
AsyncTask
的使用步驟有3個:
- 建立
AsyncTask
子類 & 根據需求實現核心方法 - 建立
AsyncTask
子類的例項物件(即 任務例項) - 手動呼叫
execute(()
從而執行非同步執行緒任務
- 具體介紹如下
/**
* 步驟1:建立AsyncTask子類
* 注:
* a. 繼承AsyncTask類
* b. 為3個泛型引數指定型別;若不使用,可用java.lang.Void型別代替
* c. 根據需求,在AsyncTask子類內實現核心方法
*/
private class MyTask extends AsyncTask<Params, Progress, Result> {
....
// 方法1:onPreExecute()
// 作用:執行 執行緒任務前的操作
// 注:根據需求複寫
6. 例項講解
下面,我將用1個例項講解 具體如何使用 AsyncTask
6.1 例項說明
- 點選按鈕 則 開啟執行緒執行執行緒任務
- 顯示後臺載入進度
- 載入完畢後更新UI元件
- 期間若點選取消按鈕,則取消載入
如下圖
示意圖
6.2 具體實現
建議先下載原始碼再看:Carson_Ho的Github地址:AsyncTask
- 主佈局檔案:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context="com.example.carson_ho.handler_learning.MainActivity">
<Button
android:layout_centerInParent="true"
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="點我載入"/>
<TextView
android:id="@+id/text"
android:layout_below="@+id/button"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="還沒開始載入!" />
<ProgressBar
android:layout_below="@+id/text"
android:id="@+id/progress_bar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:progress="0"
android:max="100"
style="?android:attr/progressBarStyleHorizontal"/>
<Button
android:layout_below="@+id/progress_bar"
android:layout_centerInParent="true"
android:id="@+id/cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="cancel"/>
</RelativeLayout>
- 主邏輯程式碼檔案:MainActivity.java
public class MainActivity extends AppCompatActivity {
// 執行緒變數
MyTask mTask;
// 主佈局中的UI元件
Button button,cancel; // 載入、取消按鈕
TextView text; // 更新的UI元件
ProgressBar progressBar; // 進度條
/**
* 步驟1:建立AsyncTask子類
* 注:
* a. 繼承AsyncTask類
* b. 為3個泛型引數指定型別;若不使用,可用java.lang.Void型別代替
* 此處指定為:輸入引數 = String型別、執行進度 = Integer型別、執行結果 = String型別
* c. 根據需求,在AsyncTask子類內實現核心方法
*/
private class MyTask extends AsyncTask<String, Integer, String> {
// 方法1:onPreExecute()
// 作用:執行 執行緒任務前的操作
@Override
protected void onPreExecute() {
text.setText("載入中");
// 執行前顯示提示
}
// 方法2:doInBackground()
// 作用:接收輸入引數、執行任務中的耗時操作、返回 執行緒任務執行的結果
// 此處通過計算從而模擬“載入進度”的情況
@Override
protected String doInBackground(String... params) {
try {
int count = 0;
int length = 1;
while (count<99) {
count += length;
// 可呼叫publishProgress()顯示進度, 之後將執行onProgressUpdate()
publishProgress(count);
// 模擬耗時任務
Thread.sleep(50);
}
}catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
// 方法3:onProgressUpdate()
// 作用:在主執行緒 顯示執行緒任務執行的進度
@Override
protected void onProgressUpdate(Integer... progresses) {
progressBar.setProgress(progresses[0]);
text.setText("loading..." + progresses[0] + "%");
}
// 方法4:onPostExecute()
// 作用:接收執行緒任務執行結果、將執行結果顯示到UI元件
@Override
protected void onPostExecute(String result) {
// 執行完畢後,則更新UI
text.setText("載入完畢");
}
// 方法5:onCancelled()
// 作用:將非同步任務設定為:取消狀態
@Override
protected void onCancelled() {
text.setText("已取消");
progressBar.setProgress(0);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 繫結UI元件
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
cancel = (Button) findViewById(R.id.cancel);
text = (TextView) findViewById(R.id.text);
progressBar =