Binder对象存储在哪里,谁引用了它

几个非常好的问题,写出来分享给大家。

  1. 多个客户端都去 bind 同一个 service,那么 service 返回的是同一个 stub 对象,还是多个 stub 对象?

  2. Binder 对象存储在 AMS 中吗?

  3. 如果不在 AMS 中,会存储在哪里?谁引用了它?

这几个问题,问的非常的好,如果想要回答这些问题,需要理清楚 Service 注册和通信的过程。文末有答案,不想看过程的,可以直接跳转到文末。

注册 Service

创建一个继承 Service 的子类,实现 onBind() 方法,并在 AndroidManifest.xml 文件中进行注册,

public class MyService extends Service {
   // 实现了 AIDL 接口 Stub 的子类
   private final IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
       public int performOperation(int num1, int num2) throws RemoteException {
           // 实现你的Service操作
           return num1 + num2;
      }
  };

   @Override
   public IBinder onBind(Intent intent) {
       return mBinder;
  }
}
  • onBind() 方法是 Service 类的一个抽象方法,必须在子类中实现。

  • onBind() 方法中,需要返回一个实现了 Stub 类的实例,这个 Stub 类继承自 Android.os.Binder 并实现了 AIDL 接口,该接口是 Service 与客户端通信的通道。

与 AMS 通信

我们可以调用 bindService() 方法启动或绑定 Service,通过 Intent 对象与 ActivityManagerService (AMS) 通信。

当 Service 被创建后,AMS 负责调用其生命周期方法,如 onCreate(), onStartCommand(), onBind() 等。

AMS 记录 Binder 对象

当调用 startService()bindService() 方法请求绑定到 Service 时,进入 AMS 处理流程。

AMS 会调用 Service 的 onBind() 方法,此方法需要返回一个 IBinder 对象,这是一个 Stub 类的实例,该对象是 Service 与客户端通信的接口。

一旦 Service 通过 onBind() 方法返回了 IBinder 对象,AMS 就会调用 publishService 来记录 Binder 对象。

图片

publishService 在 AMS 中是实现 Service 组件跨进程通信的关键方法,这个方法内部,通过 ServiceRecord 记录当前的 Binder 对象,并将 Service 注册到 ServiceManager 中。

ServiceRecord 类表示了一个 Service 的所有信息,包括它的状态和绑定的客户端。在处理绑定请求时,如果 ServiceRecord 已经存在,AMS 就会直接使用该记录中的 Binder 对象。

当 Service 被绑定时,onBind() 方法返回的 IBinder 对象会被传递给绑定的客户端。这样客户端就可以通过这个 IBinder 与 Service 进行通信。

AMS 保持对这个 IBinder 对象的引用,以便管理 Service 的生命周期和跨进程通信。

Service 与客户端之间的通信

客户端可以通过 ServiceConnection 回调接口接收到 IBinder 对象,并通过它与 Service 进行通信。

ServiceConnection connection = new ServiceConnection() {
   @Override
   public void onServiceConnected(ComponentName className, IBinder service) {
       // 我们已经绑定到LocalService,将IBinder对象转换为LocalService实例并使用
       LocalBinder binder = (LocalBinder) service;
       myService = binder.getService();
       isBound = true;
  }

   @Override
   public void onServiceDisconnected(ComponentName arg0) {
       // 当与Service的连接意外断开时调用(如Service崩溃)
       isBound = false;
  }
};

onServiceConnected() 回调中,客户端接收到 IBinder 对象,可以转换为 Service 的内部类实例,并调用 Service 的方法。

总结

了解完这个过程之后,我们依次回答一下上面的问题。

多个客户端都去 bind 同一个 service,那么 service 返回的是同一个 stub 对象,还是多个 stub 对象

无论有多少客户端绑定到同一个 Service,Service 通常返回的是同一个 Stub 对象的引用,所有客户端共享同一个 Service 的 Stub 对象。这种设计使得 Service 能够有效地管理和维护所有的客户端连接,同时避免了无谓的资源开销与复杂度。

通过 AIDL 定义的 Service,Android 会为 Service 的每个方法生成一个 Stub 类。在 Service 类 onBind 方法中,返回一个 IBinder 对象,这是一个 Stub 类的实例。

在处理请求过程中,AMS 会调用 publishService 方法,这个方法内部通过 ServiceRecord 记录当前的 Binder 对象,ServiceRecord 类表示了一个 Service 的所有信息,包括它的状态和绑定的客户端。如果 ServiceRecord 已经存在,AMS 就会直接使用该记录中的 Binder 对象。

Binder 对象存储在 AMS 中吗

AMS 作为系统的 Service 管理组件,负责协调和管理应用的组件。它在系统进程中运行,不直接存储 Service 的 Binder 对象。

AMS 通过维护 Service 的状态和连接信息来管理 Service,但具体的 Service 实例和它的 Binder 对象是在 Service 自己的进程空间中创建的。

Binder 对象存储在哪里,谁引用了它

当回调 Service 的 onBind() 方法时,该方法会返回一个 IBinder 对象,这是一个 Stub 类的实例。

当 Service 被创建时,Binder 对象也会被实例化并存储在 Service 所在的进程中。AMS 会持有这 Binder 对象的引用。

每个客户端获得的代理(Proxy)对象存储在各自客户端的进程内存空间中。这些代理对象负责将调用请求通过 Binder 驱动转发给 Service 进程。

另外 Binder 驱动作为中介在内核空间管理进程间的通信,数据在传递过程中存储在内核的 Binder 缓冲区中,直到被目标进程接收。

转自:Binder对象存储在哪里,谁引用了它

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值