对AIDL的理解

来源:互联网 发布:域名备案掉了怎么办 编辑:程序博客网 时间:2024/06/06 16:28

AS只有build之后才能将.aidl文件转换为.java文件

AILD(只支持方法,不支持静态变量)语法 

基本类型

  1)Java的4类8种基本类型。byte,short(因为Parcel不支持short,而AIDL的底层需要Parcel传数据,所以AIDL也不支持short),int,long,float,double,char.(基本类型默认且只能是in);

 2)String,Charsequence;

 3)List,map(底层是靠arrayList,HashMap实现,所以发送换是接收得要是这2种)

 4)Parcelable接口的实现类;

除了1)不标数据流向之外,2),3),7)作为方法参数需要表示数据的流向.数据流向用in,out,inout表示.

in--->表示数据由客户端流向服务端,服务端的修改不会同步到客户端--->_arg0 = data.readInt();

out--->表示数据由服务端流向客户端,服务端的改变会同步到客户端--->服务端会新建一个空对象,并将服务端对此对象的修改写给reply,传给客户端。

_arg0 = new com.example.iadlserver.Person();java.util.List<java.lang.String> _result = this.basicTypes(_arg0);reply.writeNoException();reply.writeStringList(_result);
inout--->表示数据既可以从服务端流向客户端,也可以从客户端流向服务端,从客户端传给服务端的数据会同步到服务端,服务端的修改会同步到客户端----->将客户端传过来的数据接收下来,传给service中对接口的实现方法进行处理,并将服务端的修改传递给客户端。
if ((0!=data.readInt())) {_arg0 = com.example.iadlserver.Person.CREATOR.createFromParcel(data);}else {_arg0 = null;}java.util.List<java.lang.String> _result = this.basicTypes(_arg0);reply.writeNoException();reply.writeStringList(_result);

AIDL具体实现:

服务端:

定义AIDL接口,Parcelable接口的实现类需要import包,即使该实现类和aidl文件在同一个包。因为AIDL在aidl文件夹下,java文件在java文件夹下,AS的默认gradle在java文件夹,将实现Parcelable接口的java文件放在aidl文件夹下,则AS不能gradle,实现Parcelable接口的java文件放在java文件夹下,则aidl不能使用。为了解决这种问题。解决方案有2种:

解决方案一:将实现Parcelable接口的java文件放在java文件夹下,但在aidl文件夹定义一个该实现类的aidl文件,并用parcelable声明该类。

解决方案二:将实现Parcelable接口的java文件放在aidl文件夹下,改变AS默认的gradle方式,找到build。gradle文件,在Android{}中添加该语句

服务端应该开启一个Service去接收客户端的请求。实现该AIDL接口的.Stub对象

在该实现类中写服务端的处理流程。

在onbind()方法中返回。

客户端:将服务端的AIDL文件拷贝到客户端,若有Parcelable接口的实现类,按照服务端的方法操作。客户端启动Service,从Android5.0之后,Service只能通过显示启动,

绑定的服务,必须在onDestroy()中解绑服务。

这样就可以在客户端听过mBind操作服务端的方法了。

AIDL源码分析

aidl接口的.java文件的整体框架,包括一个stub和在aidl接口中声明的方法.

IMyAidlInterface.Stub.asInterface(iBinder)的返回值是一个Proxy(代理),关键代码如下:

android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.example.iadlserver.IMyAidlInterface))) {return ((com.example.iadlserver.IMyAidlInterface)iin);}return new com.example.iadlserver.IMyAidlInterface.Stub.Proxy(obj);
若客户端的iBinder和服务端在同一个进程,则返回Stub对象。否则,返回代理。

Proxy是在内部类Stub中的一个类,Stub的主要方法:

 public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags);
第一个参数表示某个方法,aidl将方法编号,根据编号执行不同的代码。data,reply封装客户端传递的参数和返回给客户端的参数。
返回值表示客户端的请求能否成功。
测试数据流向:
客户端:代码:
Person person=new Person(24,"zhangce");Person person2=new Person(24,"zhangce");Person person3=new Person(24,"zhangce");try {    Log.i(TAG, "out  person"+person.toString()+"in  person"+person2.toString()+"inout  person"+person3.toString());    mBind.basicTypes(person,person2,person3);    Log.i(TAG, "out  person"+person.toString()+"in  person"+person2.toString()+"inout  person"+person3.toString());} catch (RemoteException e) {    e.printStackTrace();}
结果:
MainActivity:out person Person{userName='zhangce',userId=24} in person Person{userName='zhangce',userId=24} 
inout person Person{userName='zhangce',userId=24} 
MainActivity:out person Person{userName=null,userId=0} in person Person{userName='zhangce',userId=24} 
inout person Person{userName='zhangce',userId=23} 

服务端:
代码 :
Log.i(TAG, "out  person"+person.toString()+"in  person"+person2.toString()+"inout  person"+person3.toString());person.setUserId(23);person2.setUserId(23);person3.setUserId(23);Log.i(TAG, "out  person"+person.toString()+"in  person"+person2.toString()+"inout  person"+person3.toString());
结果:
MainActivity:out person Person{userName=null,userId=0} in person Person{userName='zhangce',userId=24} 
inout person Person{userName='zhangce',userId=24} 
MainActivity:out person Person{userName=null,userId=23} in person Person{userName='zhangce',userId=23} 
inout person Person{userName='zhangce',userId=23} 
1 0
原创粉丝点击