Android IPC机制

2019-08-08  本文已影响0人  在下陈小村

什么是IPC,inter_process Communication的缩写,说人话:进程间通信。

三个问题:
1.进程和线程有什么区别,是什么关系。
2.为什么要采用多进程,在什么情况下用。
3.Android中有哪些进程间通信的方式。

第一个问题:
线程是CPU调度的最小单元,是一种有限的系统资源,而进程指执行单元,一个程序或者一个应用。一个进程能够包含多个线程。
扩展:在Android里面只有主线程也就是UI线程可以操作界面元素。耗时的操作比如网络下载放在主线程操作的话,可能引起ANR异常,即应用无响应。所以耗时操作需要另起线程。

第二个问题:
一是自身某些原因需要,比如某些模块需要单独的进程,二是是要从其他程序里边获取数据,比如拿通讯录数据。

第三个问题:
bundle、文件共享、AIDL、Messenger、ContentProvider、Socket、binder

进程的其他知识点
1.Android中一个应用开启多进程只能是给四大组件在注册时加上android:process属性,“:remote”表示当前进程的私有进程,不能和其他应用的组件跑在一起,而不以:开头的进程,表示全局进程,其他应用可以通过ShareUID和他跑在一起。
2.Android系统会为每个应用分配一个UID,当ShareUID和包名都相同的情况下,才可以跑在同一个进程当中,这时他们就相当于一个应用的两个部分,能够共享内存和数据。
3.通过给一个应用创建多个进程,然后应用中包含一个带有静态变量的实体类,再通过某一个进程为这个实体类的静态变量修改值,最后分别在这三个进程中打印实体类的静态变量的值。结果发现静态变量的值只在被改变的进程当中有效,其他进程中保持初始值。由此可以得出Android为每个进程都分配了一个独立的虚拟机,不同虚拟机在内存分配上有不同的地址空间,这就导致在不同的虚拟机访问同一个类的对象会产生很多副本。这就导致不同进程之间不能通过内存来共享数据。具体表现如下
(1)静态成员和单例模式完全失效
(2)线程同步机制完全失效
(3)SharePreferences的可靠性下降
(4)Application会被多次创建
关于ShareUID可以看一下## Android ShareUserId 使用总结

IPC的基础知识
为了更好的了解IPC的知识,就必须了解序列化和反序列化的知识(Serializable和Parcelable),以及Binder。

Serializable接口
这是一个Java提供序列化的接口,serialVersionUID,是序列化和反序列化的一个标识码,系统会根据类结构生成一个serialVersionUID,当类添加或者删除了成员变量,那么serialVersionUID值就会发生变化,这将导致之前序列化好的文件再进行反序列化时报错,所以最好手动指定一个serialVersionUID。

Parcelable接口
专门为Android设计的一个序列化接口,相对于Serializable,使用起来会复杂一点,但是效率更高。

Binder


image.png
image.png

进程间通信的几种方式
(1)Bundle
启动另一个进程的四大组件,通过Intent传递附加在Bundle里面的数据。这个是最简单的进程间通信。
(2)使用文件共享
就是在一个进程中把数据序列化写入文件中,然后在另一个进程中反序列化。需要注意的是Android中并发读写可能会导致数据的错误。所以这种方式最好是在低并发的情况下使用。
(3)Messenger
说白了就是使用Messenger携带Bundle数据,然后MessengerHandler读取数据,服务端和客户端相互绑定以后,相互发送数据,其底层实现就是AIDL。
(4)AIDL
1.服务端
服务端创建一个service来监听客户端的连接请求,然后创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件中声明,最后在Service中实现这个AIDL接口。
2.客户端
绑定服务端的接口,将绑定成功后的Binder对象转换成AIDL接口所属的类型,然后调用AIDL的方法。
3.AIDL文件的创建
AIDL支持的数据类型,包括基本数据类型(int,double,long,char,boolean),String和CharSequence,List只支持ArrayList里面每个元素都必须被AIDL支持,Map和List一样,所有实现了Parcelable接口的对象,所有的AIDL接口本身也可以在AIDL中使用。
自定义的Parcelable对象和AIDL对象都必须显示的import,并且必须放在同一个包内。除了基本的数据类型,其他类型的参数必须标上in、out、inout方向。AIDL只支持方法不支持静态常量。所有的AIDL文件最好统一放在一个文件夹里面,AIDL的包结构在服务端和客户端都必须保持一致。
4.Service的实现
创建一个实现AIDL方法的Binder对象,然后在onBinder里面返回。
5.客户端实现
在绑定时转换成AIDL对象,然后调用
6.解绑时因为Binder对象在传递过程中被变换了,所以要用RemoteCalBackList来解绑。

注意线程操作,因为AIDL是耗时操作。另外可以给我们的AIDL加上权限。
(5)ContentProvider
直接通过封装的CRUD方法实现数据交互。
(6)Scoket
通过scoket网络请求相互通信。

Binder连接池
就是为了有多个AIDL接口的时候方便统一管理,只要写一个service然后加一个Binder连接池就能统一管理。

image.png
上一篇 下一篇

猜你喜欢

热点阅读