一、AsyncTask
1、概述
-
AsyncTask 是 Android 提供的一个处理异步任务的类,它可以实现主线程和后台线程的通讯,后台线程负责执行异步任务,并将结果返回给主线程
-
在 Android 开发,不能把所有的任务都放在主线程中进行实现,例如,网络操作、文件读取等,如果放在主线程中执行,会造成主线程的阻塞
2、核心组件
-
doInBackground 方法:该方法在后台线程中执行执行耗时任务,它接受一个可变参数列表,这个参数列表的类型由 AsyncTask 声明时的泛型参数确定,这个方法返回的结果会被传递给 onPostExecute 方法
-
onPostExecute 方法:当 doInBackground 方法执行完成后,该方法会在主线程中被调用,它接受 doInBackground 的返回值作为参数,通常用于更新 UI
-
onPreExecute 方法:该方法在 doInBackground 之前被调用,通常用于执行一些准备工作,例如,显示进度对话框
-
onProgressUpdate 方法: 该方法在 publishProgress 方法被调用时在主线程中执行,用于发布进度更新
二、AsyncTask 初体验
1、使用步骤
-
定义一个 AsyncTask 的子类,同时指定 3 个泛型类型参数,第 1 个参数表示传递给 doInBackground 方法的参数类型,第 2 个参数表示在后台任务执行过程中发布的进度更新类型,第 3 个参数表示后台任务完成后返回给 onPostExecute 的结果类型
-
重写 doInBackground 方法来执行后台任务,重写 onPostExecute 方法来处理任务完成后的操作
-
创建 AsyncTask 的子类的实例对象,调用 execute 方法
2、演示
(1)Activity Layout
- activity_async_task_test.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".AsyncTaskTestActivity">
<TextView
android:id="@+id/tv_res"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
(2)Activity Code
- AsyncTaskTestActivity.java
package com.my.asynctask;
import androidx.appcompat.app.AppCompatActivity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class AsyncTaskTestActivity extends AppCompatActivity {
public static final String TAG = AsyncTaskTestActivity.class.getSimpleName();
private TextView tvRes;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_async_task_test);
tvRes = findViewById(R.id.tv_res);
new TestAsyncTask().execute();
}
private class TestAsyncTask extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... voids) {
// 在这里执行耗时操作,例如,网络请求、大量计算
Log.i(TAG, "------------------------------ doInBackground executed");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Task completed!";
}
@Override
protected void onPostExecute(String s) {
// 在这里更新 UI,因为这是在主线程中执行的
Log.i(TAG, "------------------------------ onPostExecute executed");
tvRes.setText(s);
}
}
}
三、AsyncTask 生命周期
1、基本介绍
-
首先,onPreExecute 方法开始执行
-
onPreExecute 方法执行完成后,doInBackground 方法开始执行
-
如果 doInBackground 方法里面调用了 publishProgress 方法,onProgressUpdate 方法开始执行
-
最后,onPostExecute 方法开始执行
2、演示
(1)Activity Layout
- activity_async_task_life_cycle.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".AsyncTaskLifeCycleActivity">
<TextView
android:id="@+id/tv_res"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
(2)Activity Code
- AsyncTaskLifeCycleActivity.java
package com.my.asynctask;
import androidx.appcompat.app.AppCompatActivity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class AsyncTaskLifeCycleActivity extends AppCompatActivity {
public static final String TAG = AsyncTaskLifeCycleActivity.class.getSimpleName();
private TextView tvRes;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_async_task_life_cycle);
tvRes = findViewById(R.id.tv_res);
new LifeCycleAsyncTask().execute();
}
private class LifeCycleAsyncTask extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... voids) {
Log.i(TAG, "------------------------------ doInBackground 开始执行");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress();
Log.i(TAG, "------------------------------ doInBackground 执行完毕");
return "任务完成,结果数据";
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Log.i(TAG, "------------------------------ onPostExecute 开始执行");
tvRes.setText(s);
Log.i(TAG, "------------------------------ onPostExecute 执行完毕");
}
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.i(TAG, "------------------------------ onPreExecute 开始执行");
Log.i(TAG, "------------------------------ onPreExecute 执行完毕");
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
Log.i(TAG, "------------------------------ onProgressUpdate 开始执行");
Log.i(TAG, "------------------------------ onProgressUpdate 执行完毕");
}
}
}
- 输出结果
I/AsyncTaskLifeCycleActivity: ------------------------------ onPreExecute 开始执行
I/AsyncTaskLifeCycleActivity: ------------------------------ onPreExecute 执行完毕
I/AsyncTaskLifeCycleActivity: ------------------------------ doInBackground 开始执行
I/AsyncTaskLifeCycleActivity: ------------------------------ onProgressUpdate 开始执行
I/AsyncTaskLifeCycleActivity: ------------------------------ onProgressUpdate 执行完毕
I/AsyncTaskLifeCycleActivity: ------------------------------ doInBackground 执行完毕
I/AsyncTaskLifeCycleActivity: ------------------------------ onPostExecute 开始执行
I/AsyncTaskLifeCycleActivity: ------------------------------ onPostExecute 执行完毕
四、AsyncTask 实例实操
1、需求
- 模拟执行一个耗时任务,同时使用进度条来显示该耗时任务的执行进度
2、演示
(1)Activity Layout
- activity_async_task_exercise.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".AsyncTaskExerciseActivity">
<ProgressBar
android:id="@+id/pb"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
(2)Activity Code
- AsyncTaskExerciseActivity.java
package com.my.asynctask;
import androidx.appcompat.app.AppCompatActivity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ProgressBar;
public class AsyncTaskExerciseActivity extends AppCompatActivity {
public static final String TAG = AsyncTaskExerciseActivity.class.getSimpleName();
private ProgressBar pb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_async_task_exercise);
pb = findViewById(R.id.pb);
new ExerciseAsyncTask(pb).execute();
}
private class ExerciseAsyncTask extends AsyncTask<Void, Integer, Void> {
private ProgressBar progressBar;
public ExerciseAsyncTask(ProgressBar progressBar) {
this.progressBar = progressBar;
}
@Override
protected Void doInBackground(Void... voids) {
for (int i = 0; i <= 100; i += 10) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress(i);
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressBar.setProgress(values[0]);
}
}
}