这样一定能理解Binder跨进程

在Android开发中,一说到跨进程通信首先想到的就是AIDL接口,然后就是Binder通信机制。
其实,AIDL接口用起来是很简单的,但是由于接口的具体实现代码又工具生成,并且为了让它变得简单,实现中还增加了许多的“冗余”代码,导致许多人虽然用AIDL跨进程用得飞起,却始终摸不到Binder的样子。本文就是要把AIDL的实现给掰开揉碎,看看里面的Binder究竟是如何工作的。

AIDL有多简单?

如果你想试试跨进程通信,你只需要在项目中创建一个aidl文件,build之后就会看到AS已经为你创建了一个对应的java文件,其内部包含Stub类,Proxy类,以及一些其他的方法。假如我们创建了IBookManager.aidl文件,那么自动生成的IBookManager.java结构大致如下:

public interface IBookManager extends android.os.IInterface {
  //服务端进程中继承Stub类,以便处理客户端请求
  public static abstract class Stub extends Binder implements IBookManager {
      asInterface(IBinder obj){ ... }
      asBinder(){ ... }
      //处理客户端进程的请求
      onTransact(int code, Parcel data, Parcel reply, int flags) { ... }
      
      //供客户端进程使用的代理类
      private static class Proxy implements IBookManager { 
          ...
      }
  }

  //以及在IBookManager.aidl接口中定义的方法
  ...
}

这个类一般比较复杂,而且不便于理解。
然而,即使你完全不理解那些东西,也并不影响你使用AIDL来跨进程,你只需要在remote进程的Service中继承对应的Stub类并实现你aidl接口定义的方法就可以了。将复杂的跨进程通信简化到如此地步,Google也算是煞费苦心了。
具体代码这里就不贴了,网上随便搜一下AIDL就有一大堆文章告诉你。

AIDL有哪些是“多余”的?

当然,我这里说的多余,并不是说它真的多余,只是对于理解上是多余的。在具体使用中,AIDL的生成代码可谓是无懈可击的。
好了,我们接着说多余。
其实,我们要进行跨进程通信,根本不需要定义AIDL接口,不需要Stub类,不需要Proxy类,甚至不需要IInterface接口。
AIDL的核心机制就是通过Binder来实现的,只是在Binder外面包裹了几层厚毛衣,以便我们可以舒服的进行跨进程通信。
而Binder的本质是客户端通过Binder驱动像服务端进程发起请求。

那么,这个请求要如何发起呢?
就是通过IBinder.transact(…)方法,但是首先客户端得有一个从服务端进程返回的IBinder代理对象。
然后,服务端进程又是如何响应客户端请求的呢?
就是Binder中的onTransact(…)方法。

现在,要自己实现Binder通信的思路就很清晰了,只需要获取到服务端进程返回的IBinder对象,就可以向服务端进程发起请求了。然后,在服务端中实现一个继承Binder的类,来处理客户端的请求并返回结果给客户端。

当然,这只是理论,还得实践。笔者已验证确实可行。
这里简单提供一下实践的思路。

  1. 定义一个service,设置其android:process = “:remote”,即创建服务端进程。

2.在service的onBind()方法内,返回一个自己定义的类TestBinder,继承至Binder,并重写onTransact(…)方法。

3.在MainActivity中实现一个ServiceConnection,即可在bindService成功后获取到由服务端进程返回的IBinder代理对象proxyBinder。

4.通过proxyBinder.transact(…)方法,向服务端进程发起请求。

如果你每一步都做对了(可以参考aidl实现代码),你会发现你已经实现了跨进程通信。
666…

    原文作者:Javine_Kuang
    原文地址: https://www.jianshu.com/p/c2ae079b5d70
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞