5.9 KiB
5.9 KiB
AsyncTask
目录
AsyncTask原理
AsyncTask 简介
// AsyncTask:异步任务类
// 在后台线程执行任务,在主线程更新 UI
// 已废弃(Android 11+),推荐使用协程或 ExecutorService
AsyncTask 结构
public abstract class AsyncTask<Params, Progress, Result> {
// Params:参数类型
// Progress:进度类型
// Result:结果类型
// 在后台线程执行
protected abstract Result doInBackground(Params... params);
// 在主线程执行(任务开始前)
protected void onPreExecute() { }
// 在主线程执行(进度更新)
protected void onProgressUpdate(Progress... values) { }
// 在主线程执行(任务完成后)
protected void onPostExecute(Result result) { }
}
AsyncTask生命周期
生命周期方法
public class MyAsyncTask extends AsyncTask<String, Integer, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
// 主线程:任务开始前
}
@Override
protected String doInBackground(String... params) {
// 后台线程:执行任务
for (int i = 0; i < 100; i++) {
publishProgress(i); // 更新进度
}
return "Result";
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// 主线程:进度更新
int progress = values[0];
progressBar.setProgress(progress);
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// 主线程:任务完成
textView.setText(result);
}
@Override
protected void onCancelled() {
super.onCancelled();
// 主线程:任务取消
}
}
AsyncTask执行流程
执行流程
1. execute() → 创建任务
2. onPreExecute() → 主线程执行
3. doInBackground() → 后台线程执行
4. publishProgress() → 更新进度
5. onProgressUpdate() → 主线程更新 UI
6. onPostExecute() → 主线程执行(任务完成)
执行示例
// 创建并执行
MyAsyncTask task = new MyAsyncTask();
task.execute("param1", "param2");
// 取消任务
task.cancel(true);
AsyncTask问题
1. 内存泄漏
// ❌ 问题:AsyncTask 持有 Activity 引用
public class MainActivity extends AppCompatActivity {
private MyAsyncTask task;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
task = new MyAsyncTask();
task.execute();
}
// 如果 Activity 销毁,但 AsyncTask 还在执行
// Activity 无法被回收
}
2. 配置变更问题
// ❌ 问题:屏幕旋转时 Activity 重建
// AsyncTask 持有旧 Activity 引用
// 可能导致崩溃或内存泄漏
3. 串行执行
// AsyncTask 默认串行执行
// 多个 AsyncTask 按顺序执行
// 可能影响性能
4. 已废弃
// Android 11+ 已废弃 AsyncTask
// 推荐使用协程或 ExecutorService
AsyncTask替代方案
方案1:协程(推荐)
// 使用协程
lifecycleScope.launch {
val result = withContext(Dispatchers.IO) {
// 后台执行
loadData()
}
// 主线程更新 UI
updateUI(result)
}
方案2:ExecutorService
// 使用线程池
ExecutorService executor = Executors.newCachedThreadPool();
executor.execute(() -> {
// 后台执行
String result = loadData();
// 主线程更新 UI
runOnUiThread(() -> {
updateUI(result);
});
});
方案3:RxJava
// 使用 RxJava
Observable.fromCallable(() -> loadData())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
updateUI(result);
});
AsyncTask最佳实践
1. 使用静态内部类
// ✅ 使用静态内部类避免内存泄漏
private static class MyAsyncTask extends AsyncTask<String, Void, String> {
private WeakReference<MainActivity> activity;
MyAsyncTask(MainActivity activity) {
this.activity = new WeakReference<>(activity);
}
@Override
protected String doInBackground(String... params) {
// 执行任务
return null;
}
@Override
protected void onPostExecute(String result) {
MainActivity act = activity.get();
if (act != null && !act.isFinishing()) {
// 更新 UI
}
}
}
2. 及时取消
@Override
protected void onDestroy() {
super.onDestroy();
if (task != null) {
task.cancel(true);
}
}
3. 使用替代方案
// 推荐使用协程或 ExecutorService
// AsyncTask 已废弃
面试常见问题
Q1: AsyncTask 的原理?
答案:
- 在后台线程执行任务(doInBackground)
- 在主线程更新 UI(onPostExecute、onProgressUpdate)
- 使用线程池执行任务
Q2: AsyncTask 的问题?
答案:
- 内存泄漏:持有 Activity 引用
- 配置变更:屏幕旋转时可能出问题
- 串行执行:默认串行,可能影响性能
- 已废弃:Android 11+ 已废弃
Q3: AsyncTask 的替代方案?
答案:
- 协程:Kotlin 官方推荐
- ExecutorService:线程池
- RxJava:响应式编程
Q4: 如何避免 AsyncTask 内存泄漏?
答案:
- 使用静态内部类
- 使用 WeakReference
- 及时取消任务
- 使用替代方案
最后更新:2024年