Android AIDL RemoteCallbackList使用

RemoteCallbackList 使用指南

目录

概述

RemoteCallbackList 是 Android 提供的一个专门用于管理远程回调(AIDL 回调)的工具类。它解决了在跨进程通信中管理回调接口时遇到的常见问题,特别是客户端进程异常退出时的清理问题。

为什么需要 RemoteCallbackList?

在 AIDL 服务中,如果直接使用 ListCopyOnWriteArrayList 来存储回调接口,会遇到以下问题:

  1. 进程死亡检测困难:客户端进程异常退出时,服务端无法立即感知
  2. 内存泄漏风险:死亡进程的回调引用无法自动清理
  3. 回调异常:向死亡进程发送回调会导致异常
  4. 线程安全问题:需要手动处理多线程访问

RemoteCallbackList 通过 Android Binder 机制自动解决了这些问题。

核心特性

1. 自动检测进程死亡

RemoteCallbackList 内部使用 Binder 的 linkToDeath 机制,当客户端进程死亡时,会自动检测并标记回调为死亡状态。

2. 自动清理无效回调

调用 finishBroadcast() 时,会自动移除所有死亡进程的回调,防止内存泄漏。

3. 线程安全

内部已实现线程安全机制,可以在多线程环境中安全使用。

4. 防止内存泄漏

自动清理无效引用,无需手动管理回调的生命周期。

工作原理

注册回调 (register)
    ↓
Binder.linkToDeath() 监听客户端进程
    ↓
客户端进程异常退出
    ↓
Binder 检测到进程死亡
    ↓
RemoteCallbackList 标记回调为死亡状态
    ↓
发送数据时捕获 DeadObjectException
    ↓
finishBroadcast() 自动清理死亡回调
    ↓
下次发送时不再包含已死亡的回调

关键机制

  1. 注册时register() 方法会通过 Binder 的 linkToDeath 机制监听客户端进程
  2. 进程死亡时:Binder 会通知 RemoteCallbackList,回调被标记为死亡状态
  3. 广播时beginBroadcast() 获取当前有效的回调数量
  4. 清理时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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菠萝加点糖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值