Android 手写Binder 教你理解android中的进程间通信
2016-01-27 15:35
471 查看
关于Binder,我就不解释的太多了,网上一搜资料一堆,但是估计还是很多人理解的有困难。今天就教你如何从 app层面来理解好Binder。
其实就从我们普通app开发者的角度来看,仅仅对于android应用层的话,Binder就是客户端和服务端进行通信的媒介。
AIDL就是我们理解Binder 最好的事例。
我们都知道 我们写好aidl 文件以后,开发工具 会自动帮我们生成好代码。实际上 我们最终apk里面 是只有这些代码的,我们写的aidl文件
是不会被打包进去的,也就是说aidl文件 实际上 就是我们用来 生成 实际binder代码用的。所以 我们只要能够分析好,ide自动帮我们生成的
代码,就可以自己手写binder,从而在app层面上真正理解binder的用法和含义 以及原理。
首先我先来定义一个实体类:Person.java
注意看 我们这个person 类 是实现了android自带的序列化接口的,所以 如果你要在aidl里使用这个类,那你必须要额外在aidl里生命下 这个类。
好,然后给你们看一下 文件结构:
View Code
到这,我们的手写binder 就完成了,然后看看 service 以及客户端 怎么调用。
先看service:
然后看看 启动如何在客户端bind 这个service:
到这 就基本写完了,手写binder的好处就是 你可以自己在binder方法里 写一些log,能够更加深刻的认识到 Binder 作为 进程间通信 媒介的重要作用以及原理。
熟悉以后,还是用aidl 的方法 自动生成代码 最好。
其实就从我们普通app开发者的角度来看,仅仅对于android应用层的话,Binder就是客户端和服务端进行通信的媒介。
AIDL就是我们理解Binder 最好的事例。
我们都知道 我们写好aidl 文件以后,开发工具 会自动帮我们生成好代码。实际上 我们最终apk里面 是只有这些代码的,我们写的aidl文件
是不会被打包进去的,也就是说aidl文件 实际上 就是我们用来 生成 实际binder代码用的。所以 我们只要能够分析好,ide自动帮我们生成的
代码,就可以自己手写binder,从而在app层面上真正理解binder的用法和含义 以及原理。
首先我先来定义一个实体类:Person.java
package com.example.administrator.writebindercodeexample; import android.os.Parcel; import android.os.Parcelable; /** * Created by Administrator on 2016/1/27. */ public class Person implements Parcelable { private String name; public void setName(String name) { this.name = name; } public void setGender(int gender) { this.gender = gender; } public int getGender() { return gender; } public String getName() { return name; } private int gender; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.name); dest.writeInt(this.gender); } public Person() { } protected Person(Parcel in) { this.name = in.readString(); this.gender = in.readInt(); } public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() { public Person createFromParcel(Parcel source) { return new Person(source); } public Person[] newArray(int size) { return new Person[size]; } }; }
注意看 我们这个person 类 是实现了android自带的序列化接口的,所以 如果你要在aidl里使用这个类,那你必须要额外在aidl里生命下 这个类。
// Person.aidl.aidl package com.example.administrator.writebindercodeexample; // Declare any non-default types here with import statements parcelable Person;
// IPersonManager.aidl package com.example.administrator.writebindercodeexample; // Declare any non-default types here with import statements import com.example.administrator.writebindercodeexample.Person; interface IPersonManager { List<Person> getPersonList(); //关于这个参数in 其实你不加也是可以编译通过的,这里我就先加一下 具体参数的意义 以后会说 void addPerson(in Person person); }
好,然后给你们看一下 文件结构:
package com.example.administrator.writebindercodeexample; import android.os.Binder; import android.os.IBinder; import android.os.Parcel; import android.os.RemoteException; /** * Created by Administrator on 2016/1/27. */ public abstract class DogManagerImpl extends Binder implements IDogManager { public DogManagerImpl() { this.attachInterface(this, DESCRIPTOR); } public static com.example.administrator.writebindercodeexample.IDogManager asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); //如果是同1个进程,也就是说进程内通信的话 我们就返回括号内里的对象 if (((iin != null) && (iin instanceof com.example.administrator.writebindercodeexample.IDogManager))) { return ((com.example.administrator.writebindercodeexample.IDogManager) iin); } //如果不是同一进程,是2个进程之间相互通信,那我们就得返回这个Stub.Proxy 看上去叫Stub 代理的对象了 return new com.example.administrator.writebindercodeexample.DogManagerImpl.Proxy(obj); } @Override public IBinder asBinder() { return this; } @Override protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_getDogList: { data.enforceInterface(DESCRIPTOR); java.util.List<com.example.administrator.writebindercodeexample.Dog> _result = this.getDogList(); reply.writeNoException(); reply.writeTypedList(_result); return true; } case TRANSACTION_addDog: { data.enforceInterface(DESCRIPTOR); com.example.administrator.writebindercodeexample.Dog _arg0; if ((0 != data.readInt())) { _arg0 = com.example.administrator.writebindercodeexample.Dog.CREATOR.createFromParcel(data); } else { _arg0 = null; } this.addDog(_arg0); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy extends DogManagerImpl { 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.administrator.writebindercodeexample.Dog> getDogList() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.util.List<com.example.administrator.writebindercodeexample.Dog> _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(DogManagerImpl.TRANSACTION_getDogList, _data, _reply, 0); _reply.readException(); _result = _reply.createTypedArrayList(com.example.administrator.writebindercodeexample.Dog.CREATOR); } finally { _reply.recycle(); _data.recycle(); } return _result; } @Override public void addDog(com.example.administrator.writebindercodeexample.Dog dog) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); if ((dog != null)) { _data.writeInt(1); dog.writeToParcel(_data, 0); } else { _data.writeInt(0); } mRemote.transact(DogManagerImpl.TRANSACTION_addDog, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } }
View Code
到这,我们的手写binder 就完成了,然后看看 service 以及客户端 怎么调用。
先看service:
package com.example.administrator.writebindercodeexample; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import java.util.ArrayList; import java.util.List; public class RemoteService extends Service { private List<Dog> mDogsList = new ArrayList<Dog>(); private final DogManagerImpl mBinder = new DogManagerImpl() { @Override public List<Dog> getDogList() throws RemoteException { return mDogsList; } @Override public void addDog(Dog dog) throws RemoteException { mDogsList.add(dog); } }; @Override public IBinder onBind(Intent intent) { return mBinder; } }
然后看看 启动如何在客户端bind 这个service:
private IDogManager mService; private ServiceConnection sc = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = DogManagerImpl.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { mService = null; } };
到这 就基本写完了,手写binder的好处就是 你可以自己在binder方法里 写一些log,能够更加深刻的认识到 Binder 作为 进程间通信 媒介的重要作用以及原理。
熟悉以后,还是用aidl 的方法 自动生成代码 最好。
相关文章推荐
- Android traces.txt只保留最后一次发生ANR时的traces信息,那么以前的traces信息就丢失了么?
- 讨论一个Android 异步开发中容易忽视的bug
- Android之服务
- Android camera2预览界面流程
- Android内存泄漏简介
- 转载Android中全屏或者取消标题栏
- Android:我为何要封装DialogFragment?
- Android之使用 AsyncTask
- Android中滑屏实现----手把手教你如何实现触摸滑屏以及Scroller类详解
- Android之Service与IntentService的比较
- Android之异步消息处理机制
- Android Timer 定时器 与handler的配合
- [Android Pro] 使用apktool工具遇到could not decode arsc file的解决办法
- Android之多线程编程
- 五步搞定Android开发环境部署——非常详细的Android开发环境搭建教程
- android studio---Duplicate files copied in APK META-INF/LICENSE.txt 错误解决
- NotBoringActionBar项目的思路解析
- 动态加载未安装 apk: android-pluginmgr
- Android组件化小叙
- Android图文混排的实现思路