RemoteCallbackList 使用指南
目录
概述
RemoteCallbackList 是 Android 提供的一个专门用于管理远程回调(AIDL 回调)的工具类。它解决了在跨进程通信中管理回调接口时遇到的常见问题,特别是客户端进程异常退出时的清理问题。
为什么需要 RemoteCallbackList?
在 AIDL 服务中,如果直接使用 List 或 CopyOnWriteArrayList 来存储回调接口,会遇到以下问题:
- 进程死亡检测困难:客户端进程异常退出时,服务端无法立即感知
- 内存泄漏风险:死亡进程的回调引用无法自动清理
- 回调异常:向死亡进程发送回调会导致异常
- 线程安全问题:需要手动处理多线程访问
RemoteCallbackList 通过 Android Binder 机制自动解决了这些问题。
核心特性
1. 自动检测进程死亡
RemoteCallbackList 内部使用 Binder 的 linkToDeath 机制,当客户端进程死亡时,会自动检测并标记回调为死亡状态。
2. 自动清理无效回调
调用 finishBroadcast() 时,会自动移除所有死亡进程的回调,防止内存泄漏。
3. 线程安全
内部已实现线程安全机制,可以在多线程环境中安全使用。
4. 防止内存泄漏
自动清理无效引用,无需手动管理回调的生命周期。
工作原理
注册回调 (register)
↓
Binder.linkToDeath() 监听客户端进程
↓
客户端进程异常退出
↓
Binder 检测到进程死亡
↓
RemoteCallbackList 标记回调为死亡状态
↓
发送数据时捕获 DeadObjectException
↓
finishBroadcast() 自动清理死亡回调
↓
下次发送时不再包含已死亡的回调
关键机制
- 注册时:
register()方法会通过 Binder 的linkToDeath机制监听客户端进程 - 进程死亡时:Binder 会通知
RemoteCallbackList,回调被标记为死亡状态 - 广播时:
beginBroadcast()获取当前有效的回调数量 - 清理时:
finishBroadcast()会自动移除所有死亡进程的回调
API 说明
主要方法
register(E callback)
注册一个回调接口。
fun register(callback: ITestListener?): Boolean
- 参数:要注册的回调接口
- 返回:是否注册成功
- 说明:会自动监听客户端进程,如果进程死亡会自动标记
unregister(E callback)
移除一个回调接口。
fun unregister(callback: ITestListener?): Boolean
- 参数:要移除的回调接口
- 返回:是否移除成功
- 说明:如果回调不存在或已死亡,返回 false
beginBroadcast()
开始广播,返回当前有效的回调数量。
fun beginBroadcast(): Int
- 返回:当前有效的回调数量
- 说明:必须在
finishBroadcast()之前调用,且必须配对使用
getBroadcastItem(int index)
获取指定索引的回调接口。
fun getBroadcastItem(index: Int): E?
- 参数:回调索引(0 到 beginBroadcast() - 1)
- 返回:回调接口,可能为 null
- 说明:只能在
beginBroadcast()和finishBroadcast()之间调用
finishBroadcast()
完成广播,自动清理死亡进程的回调。
fun finishBroadcast()
- 说明:必须在
beginBroadcast()之后调用,且必须配对使用。会自动清理死亡进程的回调。
kill()
立即清理所有回调。
fun kill()
- 说明:清理所有回调并标记为已销毁,通常在 Service 的
onDestroy()中调用
registeredCallbackCount
获取当前注册的回调数量(只读属性)。
val registeredCallbackCount: Int
- 返回:当前注册的回调数量(包括已死亡的)
使用示例
基础示例
1. 定义 RemoteCallbackList
import android.os.RemoteCallbackList
import comTest.aidl.inter.ITestListener
object AidlManager {
// 使用 RemoteCallbackList 管理远程回调
private val mTestListeners = RemoteCallbackList<ITestListener>()
}
2. 注册和移除回调
/**
* 注册 TestListener 监听器
*/
fun registerTestListener(listener: ITestListener?) {
if (listener == null) {
Log.w(TAG, "registerTestListener: listener is null")
return
}
mTestListeners.register(listener)
Log.d(TAG, "registerTestListener: listener registered, total: ${
mTestListeners.registeredCallbackCount}")
}
/**
* 移除 TestListener 监听器
*/
fun unregisterTestListener(listener: ITestListener?) {
if (listener == null) {
Log.w(TAG, "unregisterTestListener: listener is null")
return
}
val removed = mTestListeners


9796

被折叠的 条评论
为什么被折叠?



