Binder本质上只是提供了一种通信的方式,和我们具体要实现的内容没有关系,为了实现这个服务,我们需要定义一些接口,让client能够远程调用服务,因为是跨进程,这时候就要设计到代理模式,以接口函数位基准,client和server去实现接口函数,Server是服务真正的实现,client作为一个远程的调用。

  • 从Server进程来看,Binder是存在的实体对象,client通过transact()函数,经过Binder驱动,最终回调到Binder实体的onTransact()函数中。
  • 从 Client进程的角度看,Binder 指的是对 Binder 代理对象,是 Binder 实体对象的一个远程代理,通过Binder驱动进行交互

3.手写进程通信

上面说了那么多,大家伙也看累了,下面通过代码的形式让大家对Binder加深点理解,日常开发中,涉及到进程间通信的话,我们首先想到的可能就是AIDL,但不知道有没有和我感觉一样的朋友。。第一次写AIDL是蒙蔽的,通过.aidl文件,编译器自动生成代码,生成一个java文件,里面又有Stub类,里面还有Proxy类,完全不理解里面的机制,确实不便于我们理解学习,为了加深理解,我们抛弃aidl,手写一个通信代码。

首先我们要定义一个接口服务,也就是上述的服务端要具备的能力来提供给客户端,定义一个接口继承IInterface,代表了服务端的能力

public interface PersonManger extends IInterface {
 void addPerson(Person mPerson);
 List getPersonList();
 }

接下来我们就要定义一个Server中的Binder实体对象了,首先肯定要继承Binder,其次需要实现上面定义好的服务接口

public abstract class BinderObj extends Binder implements PersonManger {
 public static final String DESCRIPTOR = “com.example.taolin.hellobinder”;
 public static final int TRANSAVTION_getPerson = IBinder.FIRST_CALL_TRANSACTION;
 public static final int TRANSAVTION_addPerson = IBinder.FIRST_CALL_TRANSACTION + 1;
 public static PersonManger asInterface(IBinder mIBinder){
 IInterface iInterface = mIBinder.queryLocalInterface(DESCRIPTOR);
 if (null!=iInterface&&iInterface instanceof PersonManger){
 return (PersonManger)iInterface;
 }
 return new Proxy(mIBinder);
 }
 @Override
 protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
 switch (code){
 case INTERFACE_TRANSACTION:
 reply.writeString(DESCRIPTOR);
 return true;case TRANSAVTION_getPerson:
 data.enforceInterface(DESCRIPTOR);
 List result = this.getPersonList();
 reply.writeNoException();
 reply.writeTypedList(result);
 return true;case TRANSAVTION_addPerson:
 data.enforceInt


erface(DESCRIPTOR);
 Person arg0 = null;
 if (data.readInt() != 0) {
 arg0 = Person.CREATOR.createFromParcel(data);
 }
 this.addPerson(arg0);
 reply.writeNoException();
 return true;
 }
 return super.onTransact(code, data, reply, flags);}
@Override
 public IBinder asBinder() {
 return this;
 }}

首先我们看asInterface方法,Binder驱动传来的IBinder对象,通过queryLocalInterface方法,查找本地Binder对象,如果返回的就是PersonManger,说明client和server处于同一个进程,直接返回,如果不是,返回给一个代理对象。

当然作为代理对象,也是需要实现服务接口

public class Proxy implements PersonManger {
 private IBinder mIBinder;
 public Proxy(IBinder mIBinder) {
 this.mIBinder =mIBinder;
 }@Override
 public void addPerson(Person mPerson) {
 Parcel data = Parcel.obtain();
 Parcel replay = Parcel.obtain();try {
 data.writeInterfaceToken(DESCRIPTOR);
 if (mPerson != null) {
 data.writeInt(1);
 mPerson.writeToParcel(data, 0);
 } else {
 data.writeInt(0);
 }
 mIBinder.transact(BinderObj.TRANSAVTION_addPerson, data, replay, 0);
 replay.readException();
 } catch (RemoteException e){
 e.printStackTrace();
 } finally {
 replay.recycle();
 data.recycle();
 }
 }@Override
 public List getPersonList() {
 Parcel data = Parcel.obtain();
 Parcel replay = Parcel.obtain();
 List result = null;
 try {
 data.writeInterfaceToken(DESCRIPTOR);
 mIBinder.transact(BinderObj.TRANSAVTION_getPerson, data, replay, 0);
 replay.readException();
 result = replay.createTypedArrayList(Person.CREATOR);
 }catch (RemoteException e){
 e.printStackTrace();
 } finally{
 replay.recycle();
 data.recycle();
 }
 return result;
 }@Override
 public IBinder asBinder() {
 return null;
 }
 }

这里的代理对象实质就是client最终拿到的代理服务,通过这个就可以和Server进行通信了,首先通过Parcel将数据序列化,然后调用 remote.transact()将方法code,和data传输过去,对应的会回调在在Server中的onTransact()中

然后是我们的Server进程,onBind方法返回mStub对象,也就是Server中的Binder实体对象

public class ServerSevice extends Service {
 private static final String TAG = “ServerSevice”;
 private List mPeople = new ArrayList<>();@Override
 public void onCreate() {
 mPeople.add(new Person());
 super.onCreate();
 }@Nullable
 @Override
 public IBinder onBind(Intent intent) {
 return mStub;
 }
 private BinderObj mStub = new BinderObj() {
 @Override
 public void addPerson(Person mPerson) {
 if (mPerson==null){
 mPerson = new Person();
 Log.e(TAG,“null obj”);
 }
 mPeople.add(mPerson);
 Log.e(TAG,mPeople.size()+"");
 }@Override
 public List getPersonList() {
 return mPeople;
 }
 };
 }

最终我们在客户端进程,bindService传入一个ServiceConnection对象,在与服务端建立连接时,通过我们定义好的BinderObj的asInterface方法返回一个代理对象,再调用方法进行交互

public class MainActivity extends AppCompatActivity {
 private boolean isConnect = false;
 private static final String TAG = “MainActivity”;
 private PersonManger personManger;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 start();
 findViewById(.textView).setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 if (personManger==null){
 Log.e(TAG,“connect error”);
 return;
 }
 personManger.addPerson(new Person());
 Log.e(TAG,personManger.getPersonList().size()+"");
 }
 });
 }private void start() {
 Intent intent = new Intent(this, ServerSevice.class);