一:Android IPC简介
IPC是Inter-Process Communication的缩写,意思就是进程间通信,两个进程之间进行数据交换的过程。什么是进程,什么是线程。按照操作系统中的描述,线程是CPU调度最小的单元,同时线程是一种有限的系统资源。而进程一般指一个执行单元,在PC和移动设备上只一个程序或者一个应用。一个进程可以包含多个线程,因此进程和线程是包含与被包含的关系。最简单的情况就是一个进程中含有一个线程,即主线程;在Android中主线程就是UI线程,在UI线程中才能操作界面元素。很多时候我们需要在线程中进行大量的耗时操作,如果我们把这些操作放在主线程中就会造成界面无法响应,即ANR(Application Not Responding)异常,解决这个问题就需要新开启另外的线程去处理这些耗时操作。
二:Android中的多进程模式
既然说到进程间的通信,所以就会涉及到多进程。
2.1开启多进程模式
在Android中使用多进程中只有一种方法,那就是给四大组件(Activity、Service、Receiver、ContentProvider)在AndroidMenifest中指定android:process属性,除此之外没有其他方法,也就是说我们无法给一个线程或者一个实体类指定其运行时所在的进程。其实还有另外一种非常规的多进程方法,那就是通过JNI在native层去fork一个新的进程。
示例:描述如何在Android中创建多进程:
<activity
android:name="com.xy.MainActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:launchMode="standard">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent,category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name="com.xy.SecondActivity"
android:comfigChanges="screenLayout"
android:label="@string/app_name"
android:process=":remote"/>
<activity
android:name="com.xy.ThirdActivity"
android:comfigChanges="screenLayout"
android:label="@string/app_name"
android:process="com.xy.remote"/>
上面的示例分别为SecondActivity和ThirdActivity指定了process属性,并且属性值不同,这就意味着当前应用增加了两个新的进程。这里有个说明":remote"和"com.xy.remote"有什么区别,“:”的含义指在当前的进程名前面附加上当前的包名,“:”还属于当前应用的私有进程,其它应用组件不可以和它跑在同一个进程中。
2.2 多进程模式的运行机制
android为每一个应用分配了一个独立的虚拟机,或者说为每一个进程都分配一个独立的虚拟机,不同的虚拟机在内存分配上有不同的地址空间,这就导致在不同的虚拟机中访问同一个对象会产生多份副本。
举个例子:
我新建一个类
public class UserManager{
public static int UserId = 1;
}
然后在MainActivity中赋值为2,打印出来,然后再启动SeconActivity,再重新打印一下,按照正常的逻辑,静态变量是可以共享的,并且一处修改处处改,但是我们运行出来发现结果却不一样,运行出来之后发现在MAinActivity中打印出来的值是2,而SecondActivity打印出来的却是1。因为在进程com.xy和进程com.xy:remote中都存在一个UserManager类,并且这两个类是互不干扰的,修改UserId的值之后修改当前类的值,对其他进程不会造成影响,所以才会出现这种情况。
这就证实了在多进程模式中,不同的进程的组件会拥有独立的虚拟机、Application已经内存空间。一般来说,多进程会造成如下方面的问题:
(1)静态成员和单例模式完全失效
(2)线程同步机制完全失效
(3)SharePreference的可靠性下降
(4)Application会多次创建
第一个问题已经解释过了,第二个:不同的内存,不管是锁对象还是锁全局类都无法保证线程同步。第三个:SharePreference不支持两个进程同时去执行读写,否则会导致一定几率的数据丢失。第四个:当一个组件跑在一个新的进程中的时候,系统会重新给他分配独立的虚拟机,其实就是把应用重新启动了一遍,那么自然会重新创建新的Application。