一般来说多进程会造成下列问题:
(1)静态成员和单例模式完全失效。
(2)线程同步机制完全失效。
已经不再同一个内存了,不管是锁对象还是锁全局类都不能保证线程同步,因为不同进程锁的不是同一个对象。
(3)SharePreferences可靠性下降。
SharePreferences不支持两个进程去同时执行写操作。因为SharePreferences的底层是通过读/写XML来实现的。
(4)Application会多次创建。
其实一个进程的创建就会伴随一Application(可以用Application中的onCreate()方法来查看PID)的创建。这样说,同一个进程是属于同一个DVM和同一个Application。 一个应用中的多个进程也相当几个不同的应用采用了ShareUID模式。
IPC基础概念
IPC的基础概念包括Serializable接口,Parcelable接口,Binder。
<关于Serializable接口>
序列化的空接口。
serialVersionUID可以定义也可以不用定义。其工作机制是在序列化的时候将serialVersionUID写入文件中,然后反序列化的时候对比文件中的ID和原ID,如果相同则可以反序列化,否则就会报错,文件在中间出现了数据的变化。 所以我们手动去定义一个UID可以很大程度保证反序列化的时候不会出错。静态成员变量因为属于类不属于对象,还有transient关键字标识的成员这些都不会参与序列化过程。
<关于Parcelable接口>
反序列方法由CREATOR来完成,其内部标明了如果创建序列化对象和数组。
假如在序列化的A类中有另外一个需要操作的别的序列化类B,则B需要反序列化需要传递当前线程的上下文类加载器,否则将无法找到类。
List和Map都可以序列化,前提是他们里面的每个元素都是可序列化的。
比较Parcelable和Serializable:
Serializable是JAVA序列化的接口,开销很大,序列化和反序列化都需要大量的I/O操作。
而Pacelable是Andorid序列化的接口,虽然写起来有点麻烦,但是效率很高,更适用于Android平台。Serializable更适合将对象序列化到存储设备中或者序列化后通过网络传输。
<关于Binder>
Binder是一个实现了IBinder接口。
Messenger的底层是AIDL。用Aidl来做例子。我们在写出MyAIDLManager.aidl后系统为我们生成了MyAIDLManager.java这个类。它继承自IInterface接口,同时自己也是一个接口,它里面声明了MyAIDLManager中我们写的方法,然后给每个方法声明了整型id去标识,就是客户端在申请的时候在transact用哪个id,就是哪个方法。接着声明Stub内部类,它是个Binder类,当客户端和服务端位于一个进程的时候不会去走transact,否则就要走transact这个过程。这个逻辑由Stub的内部类Proxy来实现。
- DESCRIPTOR
:
binder的唯一标识,一般用当前的Binder类名来表示。
- asInterface(android.os.IBinder obj)
用于将服务端的Binder对象转换成客户端所需的AIDL接口类型对象,这种转换过程是区分进程的,如果客户端和服务端位于同一个进程,那么此方法返回的就是服务端的Stub对象本身,否则返回的是系统封装后的Stub.Proxy对象。
- asBinder
返回当前的Binder对象
服务端的Stub对象本身,否则返回的是系统封装后的Stub.Proxy对象。
- asBinder
返回当前的Binder对象