您的位置:首页 > 移动开发 > Android开发

android的IPC方式 总结

2017-03-01 13:37 141 查看
对于android app开发来说android的IPC机制显得并不是这么重要,大部分的app都会是在单独进程中运行。不过对于了解android framework是非常有好处的,能够更加深入理解底层运行原理。IPC中的核心就是Binder,Binder对于应用层来说是客户端与服务器通信之后返回的Binder对象,可访问服务器方法或者与服务器传递数据。对于Framework层来说,Binder是ServiceManager与ManagerService之间的桥梁。总之,Binder在多进程通信中发挥着极为重要的作用。

IPC方式:

一、Bundle

我们知道android中的四大组件可以通过Bundle所支持的数据类型来进行跨进程通信,有一个陷阱是静态成员变量不可以在多进程中共享数据,原因是一个进程启动一个虚拟机实例,对应一个Application,也就是说当我一个进程Activity启动另外一个进程Service的时候,会创建第二个虚拟机实例,同时重新又执行了Application中的onCreate方法,这说明两个进程中的静态成员变量是互相独立的,因此无法进行数据共享。Bundle支持的数据类型包括基本数据类型、Parcelable、
Serializable等。

二、文件共享

文件共享就是说将一个进程中的数据序列化之后保存到文件中,其他线程需要反序列化之后才可以访问原始数据。文件共享数据需要处理好数据同步问题,如果多并发对文件进行读/写操作或者写操作,程序会产生不可预知的结果。android中特有的SharedPreferences是一种轻量级的数据存储方式,但是由于android在数据存储中会在内存中缓存数据,因此多并发下的数据共享非常不可靠,因此不建议采用。

三、Messenger

Messenger英文意思是信使,很好理解就是在客户端和服务器端充当信使的角色,相当于客户端和服务器端通信的媒介。Messenger底层是由AIDL(android interface define language)实现,最常用在多进程下的串行请求,服务器会把客户端发送过来的请求赛道消息队列,一个一个处理,同时如果客户端需要接受服务器返回的消息也需要通过Handler对界面更新。通过Messenger方式实现IPC流程如下:

1、Activity启动Service,Service的onBind方法返回Binder对象

2、客户端获取服务端的Messenger对象,将数据及客户端Messenger对象封装到Message,,通过Messenger发送Message到服务器端

3、服务器端通过Handler接收Message,获取Message的reply_to参数返回响应数据给客户端

4、客户端通过Handler接收数据更新UI

四、AIDL

这种方式是最标准的,也是最复杂的。支持多并发访问,通过Binder线程池来定位具体业务Binder来连接远程服务。



本文以图书馆图书为例,用户可以获取图书馆图书列表,也可以向列表添加图书。流程如下:
1、服务端先生成三个文件Book.java, Book.aidl和IBookManager.aidl,并且Book对象实现序列化接口Parcelable,Book.aidl文件是对Book类在AIDL中的声明,IBookManager.aidl是我们定义的对图书操作的接口包括addBook和getBookList两个方法,aidl后缀的文件需要import用到的类即使类是在同一个包下
2、生成服务端Service,新建Binder类继承IBookManager.Stub,对addBook和getBookList方法实现,onBind返回Binder对象
3、将1中生成的文件复制到客户端项目下(包名必须一致)
4、新建客户端Activity,客户端通过BindService绑定服务端,通过onServiceConnected方法获取到Binder对象,这里如果是同一个进程下,返回的是Stub对象,如果是跨进程下,返回的是proxy对象
5、通过返回的Binder对象,客户端可以访问服务器响应的addBook和getBookList方法
注意点:
1、AIDL支持基本数据类型,String和CharSequence
2、AIDL定义开头需要通过import引入需要用到的类即使类是在同一个包下
3、对象需要实现Parcelable接口,并且需要声明对象
4、支持集合类型List和Map,但是集合元素必须支持AIDL
5、AIDL文件本身也可以在AIDL文件中使用
6、除了基本类型以外的类型必须标注输入输出符号:in,out 或者inout
重要函数:
asInterface(IBinder) 服务器返回的Binder对象转换成客户端所需的AIDL接口类型的对象,如果客户端和服务器在同一个进程下,返回的是服务端本身的Stub对象;如果客户端和服务器端位于不同进程下,返回的是系统封装后的Stub.Proxy对象
asBinder 返回当前Binder对象
onTransact 此方法运行在服务器Binder线程池中,服务器端通过code参数确定客户端具体请求的是哪个方法,然后执行目标方法,当目标函数执行完成,在reply中写入返回值。需要注意的是当return false 表示客户端请求失败
Proxy#getBookList,Proxy#addBook 这两个方法都运行在客户端,执行过程是这样的:首先将输入参数和输出参数确定好,调用trasact函数发起RPC请求,同时线程挂起;然后服务器端的onTransact方法会被调用,知道RPC过程返回,当前线程继续执行,并从输出参数中获取返回结果

五、Socket
套接字,是网络通信概念,分为流式套接字和用户数据报套接字两种,分别是TCP和UDP;前者是面向连接的通信方式,比较可靠;后者面向无连接的通信方式,效率较高,常用在异步通信,例如广播,确定是不保证数据一定传输成功,尤其在网络拥堵的情况下。
注意点:1、利用Socket通信需要申请INTENET及ACCESS_NETWORK_STATE权限
2、访问网络必须是在子线程中进行

六、ContentProvider
ContentProvider是android专门为不同应用程序提供数据共享的方式,为进程间通信而生。ContentProvider底层也是由Binder实现,因为做了封装所以还是比较简单,Content支持表格形式,文件数据,SQLite数据和对象。创建流程如下:
1、继承Contentprovider类,并重写onCreate,query,insert等方法,注意这里onCreate是运行在主线程,query等对数据操作的函数运行在Binder线程池中
2、配置文件声明读写权限,并声明1中新建的类;android:authorities,android:name;android:permission;android:process
3、activity可以通过ContentResolver来访问ContentProvider共享的数据
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: