由于IPC机制牵扯的东西比较多,所以这里将分为一个系列进行总结
主要介绍内如如下:
- IPC简介
- Android中的多进程模式
- 开启多进程模式
- 多进程模式的运行机制
- IPC基础概念介绍
- Serializable接口
- Parcelable接口
- Binder
- Android中的IPC方式
- 使用Bundle
- 使用文件共享
- 使用Messenger
- 使用AIDL
- 使用ContentProvider
- 使用Socket
- Binder连接池
- 选用合适的IPC方式
IPC简介
IPC是Inter-Process Communication的缩写,其含义是进程间通信或者跨进程通信,是指两个进程之间进行数据交换的过程。说起进程间通信,我们首先要理解什么是进程,什么是线程,进程和线程是截然不同的概念。按照操作系统中的描述,线程是CPU调度最小的单元,同时线程是一种有限的系统资源。而进程一般指一个执行单元,在PC和移动设备上指一个应用程序或一个应用。一个进程可以包含多个线程,因此进程和线程是包含与被包含的关系。最简单的情况下,一个进程中可以只有一个线程,即主线程,在Android里面主线程也叫作UI线程,在UI线程里面才能操作界面的元素。很多时候,一个进程中需要执行大量的耗时的任务,如果这些任务放在主线程中去执行可能会造成界面无法响应,严重影响用户体验,这种情况在PC系统和移动系统中都存在,在Android中有一个特殊的名字叫做ANR(Application Not Responding),即应用无响应。解决这个问题就需要用到线程,把一些耗时的操作放到线程中去执行即可。而IPC的使用场景也很多,比如:一个应用因为某些原因自身需要采用多进程的模式来实现,至于原因,可能有很多,比如有些模块由于特殊原因需要运行在单独的进程中,又或者为了加大一个应用可使用的内存所以需要通过多进程来获取多份内存空间等等…。
Android中的多进程模式
在正式介绍进程间通信之前,我们必须先要理解Android中的多进程模式。通过给四大组件指定Android:process属性,我们可以轻易地开启多进程模式,这看起来很简单,但是实际使用过程中却暗藏杀机,多进程远远没有我们想的那么简单,有时候我们通过多进程得到的好处甚至都不足以弥补使用多进程所带来的代码层面的负面影响。下面会详细分析这些问题。
开启多进程模式
正常情况下,在Android中多进程是指一个应用中存在多个进程的情况,因此这里不讨论两个应用之间的多进程情况。首先,在Android中使用多进程只有一种方法,那就是给四大组件(Activity、Service、Receiver、ContentProvider)在AndroidMenifest文件中指定android:process属性,除此之外没有其他办法,也就是说我们无法给一个线程或者一个实体类指定其运行时所在的进程。其实还有另外一种非常规的多进程方法,那就是通过JNI在native层去fork一个新的进程,但是这种方法属于特殊情况,也不是常用的创建多进程的方式,因此我们不考虑这种方式。下面通过一个示例,描述如何Android中创建多进程:
<activity
android:name=".MainActivity"
android:configChanges="screenLayout">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SecondActivity"
android:configChanges="screenLayout"
android:launchMode="singleTask"
android:process=":remote"></activity>
<activity
android:name=".ThirdActivity"
android:configChanges="screenLayout"
android:launchMode="singleTask"
android:process="com.layoutinflate.mk.www.myapplication.remote"></activity>
上面的示例分别为SecondActivity和ThirdActivity指定了process属性,并且他们的属性值不同这意味着当前应用又增加了两个新进程。假设当前应用的包名为“com.layoutinflate.mk.www.myapplication”,当SecondActivity启动时,系统会为它创建一个单独的进程,进程名为“com.layoutinflate.mk.www.myapplication:remote”;当ThirdActivity启动时,系统也会为它创建一个单独的进程,进程名为“com.layoutinflate.mk.www.myapplication.remote”(这里需要注意的是这个进程名并不一样,SecondActivity和ThirdActivity并不在一个进程中,后面会详细讲解)。同时入口Activity是MainActivity,没有为它指定process属性,那么它运行在默认进程中,默认进程的进程名是包名。下面我们来运行下看下效果,如图所示:
可以看到进程列表中存在者3个进程,进程ID分别为:26864、27148、27174这说明我们的应用已经成功地使用了多进程技术。除了使用IDE的DDMS视图查看进程信息,还可以使用shell命令来查看,命令为:adb shell ps 或者 adb shell ps | grep com.layoutinflate.mk.www.myapplication。其中,com.layoutinflate.mk.www.myapplication是包名。
$ adb shell ps | grep com.layoutinflate.mk.www.myapplication
u0_a92 4129 32487 415604 26416 ffffffff 00000000 S com.layoutinflate.mk.www.myapplication
u0_a92 4155 32487 415636 26460 ffffffff 00000000 S com.layoutinflate.mk.www.myapplication:remote
u0_a92 4181 32487 420560 28064 ffffffff 00000000 S com.layoutinflate.mk.www