目录
第十四章:Android 多线程编程与异步任务机制(Handler、AsyncTask、线程池等)
🔸 14.5 使用 Java 原生线程池(ThreadPoolExecutor)
🔸 14.6 Kotlin 开发推荐:协程 Coroutines(了解即可)
第十四章:Android 多线程编程与异步任务机制(Handler、AsyncTask、线程池等)
Android 应用运行在单一的 UI 主线程(也叫 主线程 / UI Thread)上。为了避免阻塞界面、提升用户体验,我们需要将耗时操作(如网络请求、数据库访问、文件读写等)放到子线程中执行。本章将系统介绍 Android 中的多线程处理机制,包括 Handler、AsyncTask(已弃用但仍有参考意义)与线程池。
🔸 14.1 为什么需要多线程?
在 Android 中,所有的 UI 更新必须在主线程中执行。如下操作若直接在主线程执行,可能导致 ANR(应用无响应):
网络请求
数据库操作
大文件处理
解码操作(如 Bitmap)
🔸 14.2 Handler + Thread 模型
✦ 使用 Handler 与 Thread 进行线程通信
Handler handler = new Handler(Looper.getMainLooper());
new Thread(() -> {
// 耗时操作(如模拟网络请求)
try { Thread.sleep(2000); } catch (InterruptedException e) { }
// 回到主线程更新 UI
handler.post(() -> {
textView.setText("任务完成");
});
}).start();
✦ 简要说明:
Thread
:负责在子线程中执行耗时任务Handler.post()
:用于将 UI 更新任务发送回主线程执行
🔸 14.3 Handler 消息机制详解
Handler handler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
textView.setText("收到消息:" + msg.obj.toString());
}
}
};
new Thread(() -> {
Message message = handler.obtainMessage();
message.what = 1;
message.obj = "数据加载完成";
handler.sendMessage(message);
}).start();
🔸 14.4 AsyncTask(适用于早期项目)
⚠️ 从 Android 11 开始已被官方标记为 deprecated,但仍可用于了解异步结构设计思路。
private class MyTask extends AsyncTask<Void, Void, String> {
@Override
protected void onPreExecute() {
// 主线程:任务开始前(初始化 UI)
progressBar.setVisibility(View.VISIBLE);
}
@Override
protected String doInBackground(Void... voids) {
// 子线程:执行耗时操作
return "任务结果";
}
@Override
protected void onPostExecute(String result) {
// 主线程:任务完成后(更新 UI)
progressBar.setVisibility(View.GONE);
textView.setText(result);
}
}
// 调用方式:
new MyTask().execute();
🔸 14.5 使用 Java 原生线程池(ThreadPoolExecutor)
ExecutorService executor = Executors.newFixedThreadPool(4);
executor.execute(() -> {
// 执行耗时任务
String data = loadData();
// 回主线程更新 UI
runOnUiThread(() -> textView.setText(data));
});
✦ 优点:
避免频繁创建销毁线程
支持并发执行多个任务
适合批量任务,如多个图片下载
🔸 14.6 Kotlin 开发推荐:协程 Coroutines(了解即可)
虽然本书采用 Java 编写,但需要了解,Kotlin 开发中主流推荐使用协程 (CoroutineScope
, launch
, suspend
等),比 AsyncTask 和 Handler 更轻便灵活。
🔸 14.7 主线程中更新 UI 的常见方式总结
场景 | 方法 |
---|---|
Thread → 主线程 | Handler.post() 或 runOnUiThread() |
AsyncTask → 主线程 | onPostExecute() |
ExecutorService → 主线程 | runOnUiThread() |
✅ 总结
Android 中的 UI 必须在主线程更新,耗时任务需放入子线程执行
Handler 是 Android 最基础的线程通信工具
AsyncTask 封装了常见的异步模式(但已被弃用)
Executor 提供了线程池管理机制,适合并发任务
Kotlin 推荐使用协程,Java 可用线程池 + Handler 配合实现异步任务
📢 下一章预告:
第十五章:Android 动画机制详解(属性动画、帧动画、过渡动画)
小Demo(原来的习题板块)
项目结构
MainActivity.java
activity_main.xml
AndroidManifest.xml
1. activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点击按钮开始任务"
android:textSize="18sp"
android:gravity="center" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone" />
<Button
android:id="@+id/btnHandler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Handler + Thread 示例" />
<Button
android:id="@+id/btnAsyncTask"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="AsyncTask 示例" />
<Button
android:id="@+id/btnThreadPool"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="线程池示例" />
</LinearLayout>
2. MainActivity.java
package com.example.demo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MainActivity extends AppCompatActivity {
private TextView textView;
private ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
progressBar = findViewById(R.id.progressBar);
Button btnHandler = findViewById(R.id.btnHandler);
Button btnAsyncTask = findViewById(R.id.btnAsyncTask);
Button btnThreadPool = findViewById(R.id.btnThreadPool);
// Handler + Thread 示例
btnHandler.setOnClickListener(v -> startHandlerThreadExample());
// AsyncTask 示例
btnAsyncTask.setOnClickListener(v -> startAsyncTaskExample());
// 线程池示例
btnThreadPool.setOnClickListener(v -> startThreadPoolExample());
}
// Handler + Thread 示例
private void startHandlerThreadExample() {
progressBar.setVisibility(ProgressBar.VISIBLE);
Handler handler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
String result = (String) msg.obj;
textView.setText(result);
progressBar.setVisibility(ProgressBar.GONE);
}
}
};
new Thread(() -> {
try {
// 模拟耗时操作
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 发送消息到主线程
Message message = handler.obtainMessage();
message.what = 1;
message.obj = "Handler + Thread 示例完成";
handler.sendMessage(message);
}).start();
}
// AsyncTask 示例
private void startAsyncTaskExample() {
new MyTask().execute();
}
private class MyTask extends AsyncTask<Void, Void, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
progressBar.setVisibility(ProgressBar.VISIBLE);
}
@Override
protected String doInBackground(Void... voids) {
try {
// 模拟耗时操作
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "AsyncTask 示例完成";
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
textView.setText(result);
progressBar.setVisibility(ProgressBar.GONE);
}
}
// 线程池示例
private void startThreadPoolExample() {
progressBar.setVisibility(ProgressBar.VISIBLE);
ExecutorService executor = Executors.newFixedThreadPool(4);
executor.execute(() -> {
try {
// 模拟耗时操作
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 回到主线程更新 UI
runOnUiThread(() -> {
textView.setText("线程池示例完成");
progressBar.setVisibility(ProgressBar.GONE);
});
});
}
}
3. AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.demo">
<application
android:allowBackup="true"
android:label="多线程与异步任务示例"
android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
代码说明
1. Handler + Thread 示例
- 使用
Handler
和Thread
进行线程通信。 - 子线程完成耗时任务后,通过
Handler
将结果发送回主线程更新 UI。
2. AsyncTask 示例
- 使用
AsyncTask
执行耗时操作:onPreExecute()
:在主线程中运行,用于初始化 UI。doInBackground()
:在子线程中运行,执行耗时任务。onPostExecute()
:在主线程中运行,用于更新 UI。
3. 线程池示例
- 使用
ExecutorService
创建固定大小的线程池。 - 子线程完成任务后,通过
runOnUiThread()
更新主线程 UI。
运行效果
Handler + Thread 示例:
- 点击按钮后,进度条显示,2 秒后更新文本为“Handler + Thread 示例完成”。
AsyncTask 示例:
- 点击按钮后,进度条显示,2 秒后更新文本为“AsyncTask 示例完成”。
线程池示例:
- 点击按钮后,进度条显示,2 秒后更新文本为“线程池示例完成”。
总结
- Handler 是线程间通信的基础工具,适合简单的线程交互。
- AsyncTask 已被弃用,但在旧项目中仍常见,适合轻量级异步任务。
- 线程池 提供更高效的线程管理,适合复杂的多线程场景。
- 在现代开发中,推荐使用 Kotlin 的协程(Coroutines)或 RxJava 来处理异步任务。