AIDL和Parcelable
2015-10-29 17:37
239 查看
AIDL和Parcelable
简介
AIDL(Android Interface Definition Language)使客户端和服务端通过它定义的编程接口来达成共识,以便进行进程间通信(IPC)。仅当允许其它应用程序通过IPC方式访问Service,并且Service需要多线程运行时,才应该使用AIDL。
如果从本地进程发起调用,则调用将在调用线程中运行。
如果从远程进程发起调用,则会在Service的进程运行。
关键字oneway会改变远程调用的处理方式(该关键字只能作用于某一个接口)。远程调用不会阻塞,但本地调用仍然是同步执行的。
使用
1. 创建.aidl文件
2. 服务端实现接口并向客户端公布
3. 客户端获取接口实例
4. 服务端调用客户端
5. Parcelable
1. 创建.aidl文件在.aidl文件中,声明一个带有若干方法的接口。且只能定义一个接口,且只能包含接口的定义和方法声明。
声明的方法可带有参数和返回值,它们的类型可以为下面允许的类型。
所有非基本类型的参数都需要带有一个指明数据方向的标志。
可以是in、out、inout。
简单类型的参数默认是in,且不能是其他方向的值。
允许的类型
Java语言的所有基本类型,void,null
CharSequence
String
List,类型实参必须是这里列出的类型。实际使用的类是ArrayList
Map,类型实参必须是这里列出的类型。实际使用的类是HashMap
基于AIDL生成的接口
已声明的Parcelable类型
最后把.aidl文件放到src/目录下,在编译时,SDK工具会在gen/目录下生成IBinder接口文件。
2. 服务端实现接口并向客户端公布
.aidl文件被自动生成.java接口文件。它包含一个静态子类Stub,该子类扩展了Binder类,且实现父接口。
所以,我们应该扩展Stub,并实现由.aidl文件继承的方法。
在实现AIDL接口时的注意事项:
此接口的实现必须要保证多线程运行的安全
默认情况下,客户端调用该接口是以同步方式运行的。所以该服务的响应时间较长,则不应该在主线程中调用,而是在客户端的单独线程中调用。
所有异常都不会发还给调用者
向客户端公布接口
在onBind方法中返回该接口的实例。
3. 客户端获取接口实例
为了让客户端有权限访问接口类,客户端必须在src/目录下拥有一份.aidl文件的拷贝,用于生成供客户端访问AIDL方法的Binder接口。
在接收到回调方法onServiceConnected中的IBinder时,客户端必须调用YourServiceInterface.Stub.asInterface(service)来把返回的参数转换为YourServiceInterface类型。
之后就可以使用该接口和服务端通信了。
在调用服务器的方法时,必须要catch DeadObjectException异常,当连接中断时会抛出该异常,这是远程方法唯一抛出的异常。
4. 服务端调用客户端
通过之前的步骤,客户端已经可以调用服务端的方法了。如果服务端也想回调客户端,需要更多的步骤。
除了之前建立的.aidl文件,还需要额外简历一个.aidl文件,该文件表示客户端提供给服务端调用的接口。
之前的.aidl文件中需要增加两个方法,注册和解注册。参数为第二个.aidl文件的接口。
在服务端实现第一个接口。
实例化一个RemoteCallbackList,它是用来存储客户端接口的列表。
实现注册和解注册方法,一般为,判断参数是否为null,不为null,则调用RemoteCallbackList的方法注册/解注册。
在客户端实现第二个接口。
5. Parcelable
如果想要在AIDL中使用某个类作为参数或返回值,那么该类必须实现Parcelable接口,并且使用parcelable package.class;来声明。
实现Parcelable接口
实现describeContents方法,默认返回0就可以。
实现writeToParcel(Parcel dest, int flags)方法。该方法用于序列化,即把类中的数据写入外部的Parcel中保存。
实现静态的Parcelable.Creator接口:
createFormParcel(Parcel in)用于反序列化,该方法从Parcel中读取数据以创建对象。
newArray(int size)用于创建该类的一个数组,使用return new T[size]即可。
Parcelable和Serializable的区别
Parcelable直接在内存中读写,而Serializable读写到硬盘上。
因此,Parcelable速度也更快。而Serializable使用了反射,速度更慢。
但是因为Parcelable只在内存中读写,所以,它并不能通过网络传递,只能跨进程使用。而Serializable都可以。
参考
Service调用Client
Android AIDL中文官方文档
相关文章推荐
- [资料]Keychain 获取设备唯一
- I - Jurassic Remains
- bind() to 0.0.0.0:80 failed (98: Address already in use)
- 工作于内存和文件之间的页缓存, Page Cache, the Affair Between Memory and Files
- Container With Most Water
- 耳机与air mp3播放
- UVA - 514 Rails
- web服务器下出现大量TIME_WAIT
- int main(int argc, char *argv[])中argc和argv的解释
- 如何将Domain Users从Local Administrators Group中清除?
- UVa 10617 Again Palindrome(回文 区间dp)
- 多层嵌套对象无法使用gson反序列化的问题The JsonDeserializer com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter@3bf13cde failed to de
- pat 1079 Total Sales of Supply Chain
- Leetcode Container With Most Water
- django json http://blog.csdn.net/eengel/article/details/6198585...http://www.yihaomen.com/article/python/279.htm
- Could not obtain transaction-synchronized Session for current thread
- 5.7 Pairwise Swap
- Daily Scrum (2015/10/28)
- 栈对于表达式求值的特殊作用&&UVa442 Matrix Chain Multiplication(矩阵链乘)的理解与解析
- NetworkOnMainThreadException