AIDL in out inout 的区别
学而不思则罔,思而不学则殆
在定义AIDL的时候需要设置in out 或者 inout,开始的时候不清楚其中的区别,于是自己写了一个Demo来测试验证一下,看了很多文章,也只有自己亲自懂事试一试才能更加深刻,完整的记录下我分析的过程和源码,同大家一同分享。
Demo
https://github.com/aJanefish/BinderInOutStudy
结论
字段 | 数据流动 | 说明 |
---|---|---|
in | 客服端到服务端 | 服务端将会接收到一个那个对象的完整数据,但是客户端的那个对象不会因为服务端对传参的修改而发生变动 |
out | 服务端到客户端 | 服务端将会接收到那个对象的的空对象(默认对象),但是在服务端对接收到的空对象有任何修改之后客户端将会同步变动 |
inout | 双向的 | 服务端将会接收到客户端传来对象的完整信息,并且客户端将会同步服务端对该对象的任何变动 |
代码
// IBinderTestService.aidl
package com.zy.ipc;
import com.zy.ipc.AidlBean;
interface IBinderTestService {
void InTest(in AidlBean bean);
void InTestShow();
void OutTest(out AidlBean bean);
void OutTestShow();
void InOutTest(inout AidlBean bean);
void InOutTestShow();
}
public class AidlBean implements Parcelable {
int id;
String name;
public AidlBean() {
this(0, "DEFAULT"); //默认
}
public AidlBean(int id, String name) {
this.id = id;
this.name = name;
}
...
}
in测试
服务端如下,打印客户端传过来的参数,保留下来,更改参数:
@Override
public void InTest(AidlBean bean) throws RemoteException {
Log.d(TAG, "InTest start:" + bean);
in = bean;
bean.setId(1);
bean.setName("Service InTest");
Log.d(TAG, "InTest end:" + bean);
}
@Override
public void InTestShow() throws RemoteException {
Log.d(TAG, "InTestShow start:" + in);
in.setName("Service InTest Show");
Log.d(TAG, "InTestShow end:" + in);
}
客户端实现:
打印传入参数的前后结果,观察变化:
AidlBean inBean = new AidlBean(1000, "client inTest");
public void inTest(View view) {
try {
Log.d(TAG, "inTest start:" + inBean);
iBinderTestService.InTest(inBean);
Log.d(TAG, "inTest end:" + inBean);
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void inTestShow(View view) {
try {
//修改传入的参数
inBean.setName("client inTest Show");
Log.d(TAG, "inTestShow start:" + inBean);
iBinderTestService.InTestShow();
Log.d(TAG, "inTestShow end:" + inBean);
} catch (RemoteException e) {
e.printStackTrace();
}
}
测试inTest
结果:
08-02 06:58:29.110 4345 4345 D zhangyu.MainActivity: inTest start:AidlBean{id=1000, name='client inTest Show'}hashCode:44098254
08-02 06:58:29.111 4263 4290 D zhangyu.InOutService: InTest start:AidlBean{id=1000, name='client inTest Show'}hashCode:264932469
08-02 06:58:29.111 4263 4290 D zhangyu.InOutService: InTest end:AidlBean{id=1, name='Service InTest'}hashCode:264932469
08-02 06:58:29.111 4345 4345 D zhangyu.MainActivity: inTest end:AidlBean{id=1000, name='client inTest Show'}hashCode:44098254
in标识,客户端的参数能够传递到服务端;
hashCode不一样,标识这是两个不同的对象,说明经过Binder传输过后,已经是不同的两个对象;
服务端修改传入的参数过后,客户端的并没有被修改,结论验证成立
测试inTestShow
该方法只是修改开始的inBean对象中的数据,然后分别打印调用服务端的方法前后的结果,结果如下:
08-02 07:02:52.194 4345 4345 D zhangyu.MainActivity: inTestShow start:AidlBean{id=1000, name='client inTest Show'}hashCode:44098254
08-02 07:02:52.194 4263 4290 D zhangyu.InOutService: InTestShow start:AidlBean{id=1, name='Service InTest'}hashCode:264932469
08-02 07:02:52.195 4263 4290 D zhangyu.InOutService: InTestShow end:AidlBean{id=1, name='Service InTest Show'}hashCode:264932469
08-02 07:02:52.196 4345 4345 D zhangyu.MainActivity: inTestShow end:AidlBean{id=1000, name='client inTest Show'}hashCode:44098254
这种情况下客户端的修改不能同步到服务端
同理服务端的修改也不能同步到客户端
out测试
服务端实现:
@Override
public void OutTest(AidlBean bean) throws RemoteException {
Log.d(TAG, "OutTest start:" + bean);
out = bean;
bean.setId(2);
bean.setName("Service OutTest");
Log.d(TAG, "OutTest end:" + bean);
}
@Override
public void OutTestShow() throws RemoteException {
Log.d(TAG, "OutTestShow start:" + out);
out.setName("Service OutTest Show");
Log.d(TAG, "OutTestShow end:" + out);
}
客户端实现:
AidlBean outBean = new AidlBean(1000, "client outTest");
public void outTest(View view) {
try {
Log.d(TAG, "outTest start:" + outBean);
iBinderTestService.OutTest(outBean);
Log.d(TAG, "outTest end:" + outBean);
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void outTestShow(View view) {
try {
//修改传入的参数
outBean.setName("client outTest Show");
Log.d(TAG, "outTestShow start:" + outBean);
iBinderTestService.OutTestShow();
Log.d(TAG, "outTestShow end:" + outBean);
} catch (RemoteException e) {
e.printStackTrace();
}
}
测试OutTest
方法跟inTest一样,打印调用方法前后的对象,log如下:
08-02 07:09:15.109 4345 4345 D zhangyu.MainActivity: outTest start:AidlBean{id=2, name='client outTest Show'}hashCode:123397693
08-02 07:09:15.110 4263 4290 D zhangyu.InOutService: OutTest start:AidlBean{id=0, name='DEFAULT'}hashCode:126329866
08-02 07:09:15.110 4263 4290 D zhangyu.InOutService: OutTest end:AidlBean{id=2, name='Service OutTest'}hashCode:126329866
08-02 07:09:15.113 4345 4345 D zhangyu.MainActivity: outTest end:AidlBean{id=2, name='Service OutTest'}hashCode:123397693
现象和结论:
- hashCode不一样,客户端和服务端是不同的对象
- 服务端打印的是默认的Bean对象,说明客户端的参数没有传递到服务端,在接口用out修饰的情况下
- 服务端修改了Bean对象的值过后,客户端的值也被修改了,说明这种情况下,服务端的修改可以同步到客户端
测试OutTestShow
08-02 07:09:37.648 4345 4345 D zhangyu.MainActivity: outTestShow start:AidlBean{id=2, name='client outTest Show'}hashCode:123397693
08-02 07:09:37.649 4263 4290 D zhangyu.InOutService: OutTestShow start:AidlBean{id=2, name='Service OutTest'}hashCode:126329866
08-02 07:09:37.649 4263 4290 D zhangyu.InOutService: OutTestShow end:AidlBean{id=2, name='Service OutTest Show'}hashCode:126329866
08-02 07:09:37.650 4345 4345 D zhangyu.MainActivity: outTestShow end:AidlBean{id=2, name='client outTest Show'}hashCode:123397693
现象和结论:
客户端和服务端的修改各不相关,不会同步
inout测试
服务端实现:
@Override
public void InOutTest(AidlBean bean) throws RemoteException {
Log.d(TAG, "InOutTest start:" + bean);
inout = bean;
bean.setId(3);
bean.setName("Service InOutTest");
Log.d(TAG, "InOutTest end:" + bean);
}
@Override
public void InOutTestShow() throws RemoteException {
Log.d(TAG, "OutTestShow start:" + inout);
inout.setName("Service InOutTest show");
Log.d(TAG, "OutTestShow end:" + inout);
}
客户端实现:
AidlBean inoutBean = new AidlBean(1000, "client inoutTest");
public void inoutTest(View view) {
try {
Log.d(TAG, "inoutTest start:" + inoutBean);
iBinderTestService.InOutTest(inoutBean);
Log.d(TAG, "inoutTest end:" + inoutBean);
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void inoutTestShow(View view) {
try {
//修改传入的参数
inoutBean.setName("client inoutTest Show");
Log.d(TAG, "inoutTestShow start:" + inoutBean);
iBinderTestService.InOutTestShow();
Log.d(TAG, "inoutTestShow end:" + inoutBean);
} catch (RemoteException e) {
e.printStackTrace();
}
}
测试InOutTest
log如下:
08-02 07:16:14.543 4345 4345 D zhangyu.MainActivity: inoutTest start:AidlBean{id=3, name='client inoutTest Show'}hashCode:12528664
08-02 07:16:14.545 4263 4290 D zhangyu.InOutService: InOutTest start:AidlBean{id=3, name='client inoutTest Show'}hashCode:41423995
08-02 07:16:14.545 4263 4290 D zhangyu.InOutService: InOutTest end:AidlBean{id=3, name='Service InOutTest'}hashCode:41423995
08-02 07:16:14.546 4345 4345 D zhangyu.MainActivity: inoutTest end:AidlBean{id=3, name='Service InOutTest'}hashCode:12528664
现象与结论:
- 不是同一对象
- 开始时打印的对象值相同。客户端对象可以传递到服务端
- 结束时打印的对象值相同。服务端对象可以传递到客户端
测试InOutTestShow
log如下:
08-02 07:16:18.197 4345 4345 D zhangyu.MainActivity: inoutTestShow start:AidlBean{id=3, name='client inoutTest Show'}hashCode:12528664
08-02 07:16:18.198 4263 4290 D zhangyu.InOutService: OutTestShow start:AidlBean{id=3, name='Service InOutTest'}hashCode:41423995
08-02 07:16:18.198 4263 4290 D zhangyu.InOutService: OutTestShow end:AidlBean{id=3, name='Service InOutTest show'}hashCode:41423995
08-02 07:16:18.199 4345 4345 D zhangyu.MainActivity: inoutTestShow end:AidlBean{id=3, name='client inoutTest Show'}hashCode:12528664
现象和结论:
客户端和服务端的修改各不相关,不会同步