我就在想,在学习Binder时怎么会跑出来这么个玩意儿------RemoteCallbackList
顾名思义,RemoteCallbackList就是一个“回调列表”,它用于在不同的组件之间传递消息或执行特定的操作。举个例子,假设我们有一个服务(Service),而其他的组件(比如Activity)需要与这个服务进行通信。我们就可以使用RemoteCallbackList,可以在服务中注册回调方法,然后其他组件可以通过这个列表将自己的回调方法添加到服务中。
注:Binder的面试为啥会出现这么一个奇怪的类,不知道细心的同学们有没有发现,我们在使用aidl进行进程间通信时,经常是客户端APP调用服务端APP代码让服务端干活。那服务端干完活了之后怎么通知我们客户端呢,就要用到RemoteCallbackList来回调啦。
也就是说当在 Android 中使用AIDL进行进程间通信时,AIDL 允许我们定义接口,并在客户端和服务端之间进行调用。在某些情况下,我们需要在服务端执行某个操作后通知客户端,这时可以使用 RemoteCallbackList。
RemoteCallbackList 是 Android 提供的一个用于管理回调接口的类,特别适用于在服务端向多个客户端发送通知。它解决了在跨进程通信中传递接口对象的问题,确保客户端能够正确接收服务端的回调。
直接上代码
步骤 1: 定义 AIDL 接口
创建一个 AIDL 接口文件 CameraService.aidl,定义客户端与服务端之间的通信接口:
// CameraService.aidl
interface CameraService {
void openCamera();
void registerCallback(ICameraCallback callback);
void unregisterCallback(ICameraCallback callback);
}
创建一个 AIDL 接口文件 ICameraCallback.aidl,定义用于客户端回调的接口:
// ICameraCallback.aidl
interface ICameraCallback {
void onCameraOpened();
}
步骤 2: 实现 AIDL 接口
在服务端(远程服务)中,创建一个继承自 Service 的服务类 CameraService,实现上述定义的 AIDL 接口:
// CameraService.kt
class CameraService : Service() {
private val callbackList = RemoteCallbackList<ICameraCallback>()
override fun onBind(intent: Intent): IBinder? {
return cameraService
}
private val cameraService = object : CameraService.Stub() {
override fun openCamera() {
// 打开摄像头的逻辑
// 通知所有注册的客户端摄像头已打开
val count = callbackList.beginBroadcast()
for (i in 0 until count) {
val callback = callbackList.getBroadcastItem(i)
try {
callback?.onCameraOpened()
} catch (e: RemoteException) {
// 处理异常
}
}
callbackList.finishBroadcast()
}
override fun registerCallback(callback: ICameraCallback?) {
callback?.let { callbackList.register(it) }
}
override fun unregisterCallback(callback: ICameraCallback?) {
callback?.let { callbackList.unregister(it) }
}
}
}
步骤 3: 客户端回调注册与接收
在客户端中,创建一个 Activity:
// MainActivity.kt
class MainActivity : AppCompatActivity() {
private var cameraService: CameraService? = null
private var cameraCallback: ICameraCallback? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 绑定服务
val intent = Intent(this, CameraService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE)
// 设置按钮点击事件
button.setOnClickListener {
// 使用协程在后台线程发送消息给服务端
lifecycleScope.launch(Dispatchers.IO) {
cameraService?.openCamera()
}
}
}
override fun onDestroy() {
super.onDestroy()
// 解绑服务
unbindService(connection)
}
private val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
cameraService = CameraService.Stub.asInterface(service)
// 创建回调对象
cameraCallback = object : ICameraCallback.Stub() {
override fun onCameraOpened() {
// 在 UI 线程中处理回调
runOnUiThread {
// 摄像头已打开的处理逻辑
// ...
}
}
}
// 注册回调
cameraService?.registerCallback(cameraCallback)
}
override fun onServiceDisconnected(name: ComponentName?) {
cameraService = null
cameraCallback = null
}
}
}
记得在 AndroidManifest.xml 文件中声明服务和权限:
<manifest>
<uses-permission android:name="android.permission.CAMERA" />
```xml
<application>
<service android:name=".CameraService" android:process=":remote" />
</application>
</manifest>
在客户端的 MainActivity 中,我们绑定了服务并在按钮的点击事件中使用协程调用 AIDL 接口的 openCamera 方法发送消息给服务端。同时,我们创建了一个 ServiceConnection 对象,以便在与服务建立或断开连接时获取服务的实例。
服务端的 CameraService 类实现了 AIDL 接口,并在 openCamera 方法中执行打开摄像头的逻辑。在摄像头成功打开后,使用 RemoteCallbackList 通知所有注册的客户端。