01-18-05 Binder代理与Stub设计
·
01-18-05 Binder代理与Stub设计
Binder代理模式
Binder是Android跨进程通信(IPC)的核心机制,使用代理模式实现。
设计模式:
Client(客户端)
↓ 调用
Proxy(代理)
↓ Binder IPC
Stub(桩)
↓ 调用
Service(服务端)
Binder核心类
IBinder接口
// IBinder.java
public interface IBinder {
/**
* 跨进程调用
*/
boolean transact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException;
/**
* 查询本地接口
*/
IInterface queryLocalInterface(String descriptor);
/**
* 判断Binder是否存活
*/
boolean isBinderAlive();
/**
* 注册死亡通知
*/
void linkToDeath(DeathRecipient recipient, int flags);
/**
* 取消死亡通知
*/
boolean unlinkToDeath(DeathRecipient recipient, int flags);
}
IInterface接口
// IInterface.java
public interface IInterface {
/**
* 获取底层Binder对象
*/
IBinder asBinder();
}
Binder类
// Binder.java
public class Binder implements IBinder {
/**
* 本地Binder调用
*/
@Override
public final boolean transact(int code, Parcel data, Parcel reply, int flags) {
// 调用onTransact处理
boolean res = onTransact(code, data, reply, flags);
return res;
}
/**
* 子类重写此方法处理请求
*/
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
// 默认实现
return false;
}
/**
* 查询本地接口
*/
@Override
public IInterface queryLocalInterface(String descriptor) {
if (mDescriptor != null && mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
}
AIDL生成的代码分析
AIDL定义
// IBookManager.aidl
package com.example.bookstore;
import com.example.bookstore.Book;
interface IBookManager {
List<Book> getBookList();
void addBook(in Book book);
Book getBookById(int bookId);
}
生成的接口
// IBookManager.java
public interface IBookManager extends android.os.IInterface {
// 获取书籍列表
public java.util.List<com.example.bookstore.Book> getBookList()
throws android.os.RemoteException;
// 添加书籍
public void addBook(com.example.bookstore.Book book)
throws android.os.RemoteException;
// 根据ID查询
public com.example.bookstore.Book getBookById(int bookId)
throws android.os.RemoteException;
// Stub类定义
public static abstract class Stub extends android.os.Binder
implements com.example.bookstore.IBookManager {
// ...
}
}
Stub类实现
// IBookManager.Stub
public static abstract class Stub extends android.os.Binder
implements com.example.bookstore.IBookManager {
// 接口描述符
private static final java.lang.String DESCRIPTOR =
"com.example.bookstore.IBookManager";
// 方法ID常量
static final int TRANSACTION_getBookList =
(android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_addBook =
(android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_getBookById =
(android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
/**
* 构造函数:注册接口
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* 将IBinder转换为接口
*/
public static com.example.bookstore.IBookManager asInterface(
android.os.IBinder obj) {
if (obj == null) {
return null;
}
// 查询本地接口
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (iin != null && iin instanceof com.example.bookstore.IBookManager) {
// 同进程:直接返回本地对象
return (com.example.bookstore.IBookManager) iin;
}
// 跨进程:返回代理对象
return new com.example.bookstore.IBookManager.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
/**
* 处理客户端请求
*/
@Override
public boolean onTransact(int code, android.os.Parcel data,
android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getBookList: {
// 1. 验证接口
data.enforceInterface(DESCRIPTOR);
// 2. 调用实现类的方法
java.util.List<com.example.bookstore.Book> _result =
this.getBookList();
// 3. 写入返回值
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
case TRANSACTION_addBook: {
// 1. 验证接口
data.enforceInterface(DESCRIPTOR);
// 2. 读取参数
com.example.bookstore.Book _arg0;
if ((data.readInt() != 0)) {
_arg0 = com.example.bookstore.Book.CREATOR
.createFromParcel(data);
} else {
_arg0 = null;
}
// 3. 调用实现类的方法
this.addBook(_arg0);
// 4. 写入返回值
reply.writeNoException();
return true;
}
case TRANSACTION_getBookById: {
// 1. 验证接口
data.enforceInterface(DESCRIPTOR);
// 2. 读取参数
int _arg0 = data.readInt();
// 3. 调用实现类的方法
com.example.bookstore.Book _result = this.getBookById(_arg0);
// 4. 写入返回值
reply.writeNoException();
if ((_result != null)) {
reply.writeInt(1);
_result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
reply.writeInt(0);
}
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
}
Proxy类实现
// IBookManager.Stub.Proxy
private static class Proxy implements com.example.bookstore.IBookManager {
// Binder对象
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
/**
* 获取书籍列表
*/
@Override
public java.util.List<com.example.bookstore.Book> getBookList()
throws android.os.RemoteException {
// 1. 创建数据包
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<com.example.bookstore.Book> _result;
try {
// 2. 写入接口描述符
_data.writeInterfaceToken(DESCRIPTOR);
// 3. 发起跨进程调用
mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
// 4. 读取返回值
_reply.readException();
_result = _reply.createTypedArrayList(
com.example.bookstore.Book.CREATOR);
} finally {
// 5. 回收数据包
_reply.recycle();
_data.recycle();
}
return _result;
}
/**
* 添加书籍
*/
@Override
public void addBook(com.example.bookstore.Book book)
throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
// 1. 写入接口描述符
_data.writeInterfaceToken(DESCRIPTOR);
// 2. 写入参数
if ((book != null)) {
_data.writeInt(1);
book.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
// 3. 发起跨进程调用
mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
// 4. 读取返回值
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
/**
* 根据ID查询
*/
@Override
public com.example.bookstore.Book getBookById(int bookId)
throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
com.example.bookstore.Book _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(bookId);
mRemote.transact(Stub.TRANSACTION_getBookById, _data, _reply, 0);
_reply.readException();
if ((0 != _reply.readInt())) {
_result = com.example.bookstore.Book.CREATOR
.createFromParcel(_reply);
} else {
_result = null;
}
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
Binder通信流程
完整调用流程
Client进程 Binder驱动 Server进程
│ │ │
│ 1. 调用Proxy.getBookList()│ │
├─────────────────────────>│ │
│ │ │
│ 2. Parcel序列化参数 │ │
│ _data.writeInt(...) │ │
│ │ │
│ 3. transact()发起IPC │ │
├─────────────────────────>│ │
│ │ 4. 传递请求 │
│ ├──────────────────────>│
│ │ │
│ │ 5. onTransact()处理 │
│ │ 读取参数 │
│ │ 调用实现方法 │
│ │ │
│ │ 6. 返回结果 │
│ │<──────────────────────┤
│ 7. 读取返回值 │ │
│<─────────────────────────┤ │
│ _reply.readList() │ │
│ │ │
│ 8. 返回给调用者 │ │
同进程优化
// Stub.asInterface()
public static IBookManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
// 查询本地接口
IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (iin != null && iin instanceof IBookManager) {
// 同进程:直接返回,无需IPC
return (IBookManager) iin;
}
// 跨进程:返回代理对象
return new Stub.Proxy(obj);
}
效果:
- 同进程:直接方法调用,无序列化开销
- 跨进程:Binder IPC,需要序列化
Binder死亡通知
DeathRecipient
class BookManagerClient(context: Context) {
private var bookManager: IBookManager? = null
private var isBound = false
// 死亡通知监听器
private val deathRecipient = IBinder.DeathRecipient {
Log.e(TAG, "BookManager服务已死亡")
// 清理资源
bookManager = null
isBound = false
// 尝试重新连接
reconnect()
}
private val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
bookManager = IBookManager.Stub.asInterface(service)
isBound = true
// 注册死亡通知
try {
service?.linkToDeath(deathRecipient, 0)
} catch (e: RemoteException) {
e.printStackTrace()
}
}
override fun onServiceDisconnected(name: ComponentName?) {
Log.w(TAG, "Service disconnected")
bookManager = null
isBound = false
}
}
fun connect() {
val intent = Intent().apply {
component = ComponentName(
"com.example.bookstore",
"com.example.bookstore.BookManagerService"
)
}
context.bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
fun disconnect() {
// 取消死亡通知
try {
bookManager?.asBinder()?.unlinkToDeath(deathRecipient, 0)
} catch (e: Exception) {
e.printStackTrace()
}
if (isBound) {
context.unbindService(connection)
isBound = false
}
}
private fun reconnect() {
// 延迟重连
Handler(Looper.getMainLooper()).postDelayed({
connect()
}, 1000)
}
companion object {
private const val TAG = "BookManagerClient"
}
}
Binder线程池
线程模型
Server进程:
├── Binder线程1
├── Binder线程2
├── Binder线程3
└── ...
特点:
- 客户端调用会在Binder线程执行
- 服务端需要考虑线程安全
线程安全
class BookManagerService : Service() {
// CopyOnWriteArrayList线程安全
private val bookList = CopyOnWriteArrayList<Book>()
// 监听器列表(线程安全)
private val listeners = RemoteCallbackList<IBookListener>()
private val binder = object : IBookManager.Stub() {
override fun getBookList(): List<Book> {
// Binder线程调用,CopyOnWriteArrayList线程安全
return ArrayList(bookList)
}
override fun addBook(book: Book?) {
book ?: return
// Binder线程调用,需要线程安全
synchronized(bookList) {
if (bookList.any { it.id == book.id }) {
return
}
bookList.add(book)
}
// 通知监听器(在Binder线程)
notifyBookAdded(book)
}
override fun registerListener(listener: IBookListener?) {
listener ?: return
// RemoteCallbackList线程安全
listeners.register(listener)
}
override fun unregisterListener(listener: IBookListener?) {
listener ?: return
listeners.unregister(listener)
}
}
override fun onBind(intent: Intent?): IBinder {
return binder
}
private fun notifyBookAdded(book: Book) {
// RemoteCallbackList遍历模式
val count = listeners.beginBroadcast()
for (i in 0 until count) {
try {
listeners.getBroadcastItem(i).onBookAdded(book)
} catch (e: RemoteException) {
e.printStackTrace()
}
}
listeners.finishBroadcast()
}
}
Binder性能优化
1. 减少IPC次数
// [未通过] 多次IPC
for (id in bookIds) {
val book = bookManager.getBookById(id) // N次IPC
books.add(book)
}
// [通过] 批量IPC
val books = bookManager.getBooksByIds(bookIds) // 1次IPC
2. 异步调用
// 异步获取书籍列表
fun loadBooks(callback: (List<Book>) -> Unit) {
CoroutineScope(Dispatchers.IO).launch {
try {
val books = bookManager?.getBookList()
withContext(Dispatchers.Main) {
books?.let { callback(it) }
}
} catch (e: RemoteException) {
e.printStackTrace()
}
}
}
3. 使用oneway修饰符
// 单向调用,不等待返回
interface IBookListener {
oneway void onBookAdded(in Book book);
oneway void onBookRemoved(in Book book);
}
特点:
- 客户端调用后立即返回,不等待服务端执行完成
- 适用于通知类方法
总结
Binder代理模式核心
- Stub:服务端实现,处理客户端请求
- Proxy:客户端代理,封装IPC细节
- asInterface:根据是否同进程返回Stub或Proxy
- onTransact:服务端处理请求
- transact:客户端发起请求
Binder通信特点
- 同进程:直接方法调用
- 跨进程:Binder IPC + 序列化
- 线程池:服务端多线程处理
- 死亡通知:监听服务端崩溃
开发建议
- 使用RemoteCallbackList管理监听器
- 注意线程安全(CopyOnWriteArrayList、synchronized)
- 注册死亡通知监听服务端状态
- 减少IPC次数,批量操作
- 使用oneway优化单向调用
Android 16 (API 36) Binder变化
Binder事务缓冲区优化
Android 16 的 Binder 事务改进:
- 增大的默认事务缓冲区大小
- 更智能的缓冲区回收策略
- 减少 TransactionTooLargeException 的发生
死亡通知增强
// Android 16:更可靠的 Binder 死亡检测
// 新增 linkToDeath 的超时机制
fun monitorServiceWithTimeout(binder: IBinder, timeoutMs: Long = 5000) {
val deathRecipient = IBinder.DeathRecipient {
Log.w(TAG, "Binder died, initiating reconnect...")
reconnectService()
}
try {
binder.linkToDeath(deathRecipient, 0)
// Android 16: 可配合 Coroutines 使用
// 新增 awaitBinderDeath 扩展
} catch (e: RemoteException) {
// 服务已经死亡
reconnectService()
}
}
Binder 线程池调优
// Android 16 默认 Binder 线程池更大
// 服务端需要注意:
// 1. 更多并发 Binder 调用可能同时到达
// 2. 使用更精细的锁策略
// 3. 避免在 Binder 线程执行耗时操作
class BookManagerService : Service() {
// 推荐使用 Dispatcher 控制并发
private val binderScope = CoroutineScope(
Dispatchers.IO.limitedParallelism(4) // 限制并发数
)
}
关键要点:Binder代理模式是Android IPC的核心,理解Stub和Proxy的实现是掌握Binder的关键
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)