一、基础通信机制
1. Handler消息机制(主线程与子线程)
// 主线程创建Handler
val mainHandler = Handler(Looper.getMainLooper())
// 子线程发送消息
thread {
mainHandler.post {
// 在主线程执行UI更新
textView.text = "更新UI"
}
}
特点:
-
适用于子线程→主线程通信
-
底层基于
MessageQueue
和Looper
-
可发送
Message
对象或Runnable
任务
2. AsyncTask(已弃用,但需了解)
object : AsyncTask<Void, Void, String>() {
override fun doInBackground(vararg params: Void): String {
return "计算结果" // 在子线程执行
}
override fun onPostExecute(result: String) {
textView.text = result // 在主线程执行
}
}.execute()
注意:Android 11后已废弃,推荐使用kotlin协程
或RxJava
二、高级通信方案
1. 共享内存 + 同步控制
// 定义共享对象
val sharedData = AtomicInteger(0)
// 线程A修改数据
thread {
sharedData.set(10)
}
// 线程B读取数据
thread {
val value = sharedData.get()
}
同步工具选择:
-
synchronized
:简单互斥 -
ReentrantLock
:可中断、公平锁选项 -
Atomic
类:无锁CAS操作(如AtomicInteger
)
2. BlockingQueue实现生产者-消费者
val queue = LinkedBlockingQueue<String>()
// 生产者线程
thread {
queue.put("数据1")
}
// 消费者线程
thread {
val data = queue.take() // 阻塞获取
println(data)
}
适用场景:
-
线程间数据传递
-
解耦生产者和消费者
三、跨进程通信(IPC)
1. Binder机制
// 服务端实现AIDL接口
class RemoteService : Service() {
private val binder = object : IMyAidlInterface.Stub() {
override fun getData(): String = "跨进程数据"
}
override fun onBind(intent: Intent) = binder
}
// 客户端绑定调用
val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
val remoteService = IMyAidlInterface.Stub.asInterface(service)
val data = remoteService.getData() // 跨进程调用
}
}
bindService(intent, connection, Context.BIND_AUTO_CREATE)
2. Messenger
// 服务端
class MessengerService : Service() {
private val handler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
// 处理客户端消息
val reply = Message.obtain()
reply.arg1 = 100
msg.replyTo.send(reply) // 回复客户端
}
}
val messenger = Messenger(handler)
override fun onBind(intent: Intent) = messenger.binder
}
// 客户端
val clientMessenger = Messenger(Handler(Looper.getMainLooper()))
bindService(intent, object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
val serverMessenger = Messenger(service)
val msg = Message.obtain().apply {
replyTo = clientMessenger // 设置回复通道
}
serverMessenger.send(msg) // 发送消息
}
}, Context.BIND_AUTO_CREATE)
四、现代通信方案
1. Kotlin协程Channel
val channel = Channel<String>()
// 生产者协程
launch {
channel.send("数据1")
}
// 消费者协程
launch {
val data = channel.receive()
println(data)
}
优势:
-
轻量级(相比线程)
-
支持挂起而非阻塞
-
结构化并发管理
2. RxJava事件总线
// 定义事件总线
object EventBus {
private val subject = PublishSubject.create<String>()
fun post(event: String) = subject.onNext(event)
fun observe(): Observable<String> = subject
}
// 发送事件
thread {
EventBus.post("新事件")
}
// 接收事件
EventBus.observe()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { event ->
textView.text = event
}
五、通信机制选型指南
场景 | 推荐方案 | 理由 |
---|---|---|
子线程→主线程更新UI | Handler /View.post() | 专为UI线程设计 |
线程间数据交换 | BlockingQueue | 线程安全队列 |
结构化异步任务 | Kotlin协程 | 代码简洁,避免回调地狱 |
跨进程通信 | Binder /Messenger | Android专属高效IPC机制 |
全局事件通知 | RxJava /LiveData | 支持多订阅和线程切换 |
六、回答要点
Q:Android中如何实现线程间通信?
A:主要有五种方式:
Handler机制:用于子线程与主线程通信,底层通过MessageQueue实现
共享变量+同步控制:使用synchronized或Lock保证线程安全
阻塞队列:如LinkedBlockingQueue实现生产者-消费者模式
协程Channel:Kotlin的轻量级通信管道
跨进程方案:Binder/Messenger用于进程间通信
Q:为什么推荐使用Handler而不是直接更新UI?
A:因为Android的UI框架不是线程安全的,Handler通过将UI操作派发到主线程的消息队列:
避免多线程竞争导致的界面异常
符合Android的单线程UI模型
提供有序的消息处理机制
Q:协程相比传统线程通信有什么优势?
A:协程的核心优势在于:
轻量级:一个线程可运行数千协程
结构化:通过作用域自动管理生命周期
非阻塞:挂起代替阻塞,提高CPU利用率
简洁性:用同步写法实现异步逻辑