AIDL学习笔记
目标:通过这个例子来介绍AIDL
Server进程注册一个Calculator服务到ServiceManager,该Calculator服务提供add和minus两个接口,Client进程通过ServiceManager获得Calculator服务的代理类,通过Binder调用add和minus两个接口。
1、没有AIDL的世界
1.1 Server进程
class Calculator extends Binder { private static final int CODE_ADD = 1; private static final int CODE_MINUS = 2; @Override protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException { if (code == CODE_ADD) { int a = data.readInt(); int b = data.readInt(); reply.writeInt(a + b); return true; } else if (code == CODE_MINUS) { int a = data.readInt(); int b = data.readInt(); reply.writeInt(a - b); return true; } return super.onTransact(code, data, reply, flags); } } void main() { //注册binder服务 ServiceManager.addService("calculator", new Calculator()); }
1.2 Client进程
private static final int CODE_ADD = 1; private static final int CODE_MINUS = 2; int add(int a, int b) { IBinder mClient = ServiceManager.getService("calculator");//BinderProxy Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInt(a); data.writeInt(b); mClient.transact(CODE_ADD, data, reply, 0); int result = reply.readInt(); return result; } int minus(int a, int b) { IBinder mClient = ServiceManager.getService("calculator");//BinderProxy Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInt(a); data.writeInt(b); mClient.transact(CODE_MINUS, data, reply, 0); int result = reply.readInt(); return result; }
2、有AIDL的世界
ICalculator.aidl文件
//aidl interface ICalculator { int add(int a, int b); int minus(int a, int b); }
2.1 Server进程
与1.1中代码比较,我们发现,我们不是直接继承Binder,而是继承ICalculator.Stub,我们只需专注写add和minus接口的实现,不需要在Binder类中的onTransact写一堆if else和Parcel.read write
class Calculator extends ICalculator.Stub { @Override public int add(int a, int b) { return a + b; } @Override public int minus(int a, int b) { return a - b; } } void main() { //注册binder服务 ServiceManager.addService("calculator", new Calculator()); }
2.2 Client进程
与1.2中代码比较,我们发现,我们不需要写Parcel.read write和BinderProxy.transact,而是用BinderProxy对象构造一个ICalculator.Stub.Proxy对象,然后直接调用ICalculator.Stub.Proxy的add和minus
int add(int a, int b) { IBinder mClient = ServiceManager.getService("calculator");//BinderProxy return new ICalculator.Stub.Proxy(mClient).add(a, b); } int minus(int a, int b) { IBinder mClient = ServiceManager.getService("calculator");//BinderProxy return new ICalculator.Stub.Proxy(mClient).minus(a, b); }
3、AIDL自动生成了什么代码
ICalculator.aidl生成的代码如下,有三个部分组成,我们后面仔细分析
ICalculator接口
ICalculator.Stub类
ICalculator.Stub.Proxy类
interface ICalculator {//看3.1分析 int add(int a, int b); int minus(int a, int b); abstract static class Stub extends Binder implements ICalculator {//看3.2分析 private static final int CODE_ADD = 1; private static final int CODE_MINUS = 2; @Override protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException { if (code == CODE_ADD) { int a = data.readInt(); int b = data.readInt(); reply.writeInt(add(a, b)); return true; } else if (code == CODE_MINUS) { int a = data.readInt(); int b = data.readInt(); reply.writeInt(minus(a, b)); return true; } return super.onTransact(code, data, reply, flags); } abstract public int add(int a, int b); abstract public int minus(int a, int b); public static class Proxy implements ICalculator {//看3.3分析 private IBinder remote; public Proxy(IBinder remote) { this.remote = remote; } @Override public int add(int a, int b) { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInt(a); data.writeInt(b); remote.transact(CODE_ADD, data, reply, 0); int result = reply.readInt(); return result; } @Override public int minus(int a, int b) { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInt(a); data.writeInt(b); remote.transact(CODE_MINUS, data, reply, 0); int result = reply.readInt(); return result; } } } }
3.1 ICalculator接口
看起来和aidl文件差不多
interface ICalculator { int add(int a, int b); int minus(int a, int b); }
3.2 ICalculator.Stub类
继承于Binder,实现ICalculator接口,但是是空实现,然后在onTransact方法中调用空实现的add和minus接口
abstract static class Stub extends Binder implements ICalculator { private static final int CODE_ADD = 1; private static final int CODE_MINUS = 2; @Override protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException { if (code == CODE_ADD) { int a = data.readInt(); int b = data.readInt(); reply.writeInt(add(a, b)); return true; } else if (code == CODE_MINUS) { int a = data.readInt(); int b = data.readInt(); reply.writeInt(minus(a, b)); return true; } return super.onTransact(code, data, reply, flags); } abstract public int add(int a, int b); abstract public int minus(int a, int b); }
3.3 ICalculator.Stub.Proxy类
用 BinderProxy 构造 ICalculator.Stub.Proxy,把调用 ICalculator.Stub.Proxy 的add和minus接口转化成 Parcel.write,read 和 BinderProxy.transact 代码。
public static class Proxy implements ICalculator { private IBinder remote; public Proxy(IBinder remote) { this.remote = remote; } @Override public int add(int a, int b) { Parcel data = Parcel.obtain(); data.writeInt(a); data.writeInt(b); Parcel reply = Parcel.obtain(); remote.transact(CODE_ADD, data, reply, 0); int result = reply.readInt(); return result; } @Override public int minus(int a, int b) { Parcel data = Parcel.obtain(); data.writeInt(a); data.writeInt(b); Parcel reply = Parcel.obtain(); remote.transact(CODE_MINUS, data, reply, 0); int result = reply.readInt(); return result; } }
总结
看完应该明白了AIDL作用主要有
a.偷懒,少很多代码,尤其是你要写上百个方法的时候,AIDL就派上大用场了。
b.让服务端更专注接口的实现,而减少犯错误的可能性
c.规范client端和server端的接口定义,有助于代码的迭代
当然这是我自己写的伪代码,AIDL真正生成的代码更加复杂一点,但这些伪代码就是AIDL核心点。
思考: oneway的这个语法对AIDL生成的代码有什么影响,或者你们自己写一下oneway的方法AIDL生成的伪代码.
参考:
十分钟让你明白AIDL:https://www.jianshu.com/p/8f9e9147f5ba
posted on 2020-09-26 19:40 Hello-World3 阅读(336) 评论(0) 编辑 收藏 举报