在Android开发中,线程间通信(IPC)是处理多线程协作的核心技术。Android提供了多种线程通信机制,各有特点和适用场景。
一、基础通信方式
1. Handler/Looper/MessageQueue机制
核心组件:
-
Handler:消息发送和处理
-
Looper:消息循环
-
MessageQueue:消息队列
典型实现:
// 工作线程发送消息
new Thread(() -> {
Message msg = Message.obtain();
msg.what = 1;
msg.obj = "Data from worker";
mainHandler.sendMessage(msg);
}).start();
// 主线程Handler
Handler mainHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
String data = (String) msg.obj;
textView.setText(data);
break;
}
}
};
特点:
-
精确控制消息处理时机
-
适合主线程与工作线程通信
-
内存效率高(Message可复用)
二、高级通信方式
2. AsyncTask(已弃用,但需了解)
private class MyTask extends AsyncTask<String, Integer, String> {
@Override
protected String doInBackground(String... params) {
// 后台执行
publishProgress(50); // 更新进度
return "Result";
}
@Override
protected void onProgressUpdate(Integer... values) {
// UI线程更新进度
progressBar.setProgress(values[0]);
}
@Override
protected void onPostExecute(String result) {
// UI线程处理结果
textView.setText(result);
}
}
注意:Android 11已标记为弃用,推荐使用协程或RxJava替代。
3. Executor框架 + Activity.runOnUiThread
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> {
// 后台工作
final String result = doWork();
// 返回主线程
runOnUiThread(() -> {
textView.setText(result);
});
});
三、现代通信方式
4. Kotlin协程
// 在ViewModel或LifecycleOwner中
lifecycleScope.launch {
// 主线程执行
val deferred = async(Dispatchers.IO) {
// IO线程执行耗时操作
fetchDataFromNetwork()
}
// 自动切换回主线程
val result = deferred.await()
updateUI(result)
}
优势:
-
结构化并发
-
自动线程切换
-
取消传播
5. RxJava
Observable.fromCallable(() -> {
// 子线程执行
return fetchData();
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
// 主线程更新UI
textView.setText(result);
}, error -> {
// 错误处理
});
四、跨进程通信方式
6. Binder机制
AIDL接口示例:
// IMyService.aidl
interface IMyService {
int add(int a, int b);
}
// 服务端实现
private final IMyService.Stub binder = new IMyService.Stub() {
@Override
public int add(int a, int b) {
return a + b;
}
};
// 客户端绑定
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IMyService myService = IMyService.Stub.asInterface(service);
int result = myService.add(1, 2);
}
};
7. Messenger
// 服务端
Handler handler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
// 处理消息
Message reply = Message.obtain();
try {
msg.replyTo.send(reply);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
Messenger messenger = new Messenger(handler);
// 客户端
Messenger clientMessenger = new Messenger(new Handler());
Message msg = Message.obtain();
msg.replyTo = clientMessenger;
serviceMessenger.send(msg);
五、数据共享方式
8. 共享内存
// 使用并发集合
ConcurrentHashMap<String, Object> sharedMap = new ConcurrentHashMap<>();
// 使用Atomic类
AtomicInteger counter = new AtomicInteger(0);
// 使用Android的MemoryFile
MemoryFile memoryFile = new MemoryFile("shared_mem", 1024);
9. LiveData
// ViewModel中
MutableLiveData<String> data = new MutableLiveData<>();
// 观察者
data.observe(this, new Observer<String>() {
@Override
public void onChanged(String value) {
// UI线程自动更新
textView.setText(value);
}
});
// 工作线程更新
executor.execute(() -> {
String result = fetchData();
data.postValue(result); // 非UI线程使用postValue
});
六、对比与选型建议
通信方式 | 适用场景 | 线程安全 | 跨进程 | 学习曲线 |
---|---|---|---|---|
Handler | 主线程与工作线程通信 | 是 | 否 | 低 |
AsyncTask | 简单后台任务(已弃用) | 部分 | 否 | 低 |
Executor | 线程池管理 | 需自行保证 | 否 | 中 |
协程 | 现代异步编程 | 是 | 否 | 中高 |
RxJava | 复杂异步流 | 是 | 否 | 高 |
Binder | 跨进程通信 | 是 | 是 | 高 |
Messenger | 简单跨进程消息 | 是 | 是 | 中 |
LiveData | UI数据驱动 | 是 | 否 | 中 |
选型建议:
-
简单UI更新:Handler或LiveData
-
复杂异步流:RxJava或协程
-
线程池任务:Executor框架
-
跨进程通信:Binder或Messenger
-
新项目推荐:Kotlin协程 + LiveData
七、最佳实践
-
避免内存泄漏
// 使用弱引用 private static class MyHandler extends Handler { private final WeakReference<Activity> mActivity; MyHandler(Activity activity) { mActivity = new WeakReference<>(activity); } @Override public void handleMessage(Message msg) { Activity activity = mActivity.get(); if (activity != null) { // 处理消息 } } }
-
线程切换明确
viewModelScope.launch { // 主线程开始 val result = withContext(Dispatchers.IO) { // IO线程执行 repository.loadData() } // 自动切换回主线程 updateUI(result) }
-
异常处理完善
executor.execute(() -> { try { doWork(); } catch (Exception e) { runOnUiThread(() -> showError(e)); } });
通过合理选择线程通信方式,可以构建出高效、稳定的Android应用架构。在实际开发中,应根据具体场景选择最适合的方案,并注意线程安全和性能优化。