Android 开发艺术探索读书笔记 2 -- IPC 机制
hello,夏天 (图片来源于网络)本篇文章主要介绍以下几个知识点:
- Android IPC简介;
- Android 中的多进程模式 ;
- IPC基础概念介绍 。
2.1 Android IPC简介
IPC 是 Inter-Process Communication 的缩写,含义是进程间通信或跨进程通信,指两个进程间进行数据交互的一个过程。
-
线程:是CPU调度的最小单元,同时是一种有限的系统资源
-
进程:一般指一个执行单元,在PC和移动设备上指一个程序或一个应用
一个进程可包含多个线程,进程和线程是包含与被包含的关系。
最简单的情况下,一个进程中可以只有一个线程,即主线程,在 Android 里主线程也叫 UI 线程,在 UI 线程里才能操作界面元素。
若一个进程中要执行大量耗时的任务,把这些任务放在主线程中去执行就会造成界面无法响应,在 Android 中叫做 ANR (Application Not Responding),即应用无响应,这时要把这些耗时的任务放在线程中即可。
2.2 Android 中的多进程模式
Android 中通过给四大组件指定 android:process
属性,可轻易开启多进程模式,但实际使用过程中却暗藏杀机,甚至弊大于利。
2.2.1 开启多进程模式
正常情况下,在 Android 中多进程是指一个应用中存在多个进程的情况,这里不讨论两个应用之间的情况。
在 Android 中使用多进程只有一种方法,那就是给四大组件指定 android:process,即无法给一个线程或实体类指定其运行时所在的进程(通过 JNI 在 native 层去 fork 一个新的进程,是一种非常规的创建多进程方式,暂不考虑此方式),如下:
<!-- 没指定 process 属性,运行在默认进程中 -->
<activity
android:name=".chapter02.Chapter02Activity"/>
<!-- 当 SecondActivity 启动时,系统会为它创建一个单独的进程,
进程名:com.wonderful.androidartexplore:remote -->
<activity
android:name=".chapter02.SecondActivity"
android:process=":remote"/>
<!-- 当 ThridActivity 启动时,系统也会为它创建一个单独的进程,
进程名:com.wonderful.androidartexplore.remote -->
<activity
android:name=".chapter02.ThirdActivity"
android:process="com.wonderful.androidartexplore.remote"/>
上面分别为 SecondActivity 和 ThirdActivity 指定了 process
属性,当运行程序时发现进程列表末尾存在三个进程,说明成功的开启了多进程。
上面 SecondActivity 和 ThirdActivity 的进程名分别为:remote 和 包名.remote,有两方面区别:
1. “:”的含义是指在当前的进程名前附加上包名,是一种简单写法,SecondActivity 的完整进程名为 com.wonderful.androidartexplore:remote
,而 ThirdActivity 中的申明方式,是一种完整的命名方式,不会附加包名信息;
2. 进程以”:“开头的属于当前应用的私有进程,其他应用的组件不可以和它跑在同一个进程中,而进程名不以”:“开头的进程属于全局进程,其他应用通过ShareUID方式可以和它跑在同一进程中。
2.2.2 多进程模式的运行机制
所有运行在不同进程中的四大组件,只要它们之间需要通过内存来共享数据,都会共享失败,这也是多进程带来的主要影响,正常情况下四大组件中间不可能不通过一些中间层来共享数据,那么通过简单地指定进程名来开启多进程都会无法正确运行。
当然,特殊情况下,某些组件之间不需要共享数据,这时可直接指定 android:process
属性来开启多进程,但这种场景不常见,几乎所有情况都需要共享数据。
一般来说,使用多进程会造成如下几方面的问题:
(1)静态成员和单例模式完全失效。
(2)线程同步机制完全失效。
(3)SharedPreferences的可靠性下降。
(4)Application会多次创建。
对于问题1,Android 为每个进程都分配一个独立的虚拟机,不同的虚拟机在内存上有不同的地址空间,这就导致在不同的虚拟机中访问同一个类的对象会产生多份副本。
对于问题2,本质上和第一个问题是类似的,既然都不是一块内存了,那么不管是锁对象还是锁全局类都无法保证线程同步,因为不同进程锁都不是同一个对象。
对于问题3,是因为SharedPreferences
不支持两个进程同时去执行写操作,否则会导致一定几率的数据丢失,这是因为SharedPreferences
底层是通过读/写XML文件来实现的,并发读/写都有可能出问题
对于问题4,当一个组件跑在一个新的进程中时,由于系统要在创建新的进程同时分配独立的虚拟机,此过程就是启动一个应用的过程,相当于系统又把这个应用重启动了一遍,从而创建新的 Application。
或者说,运行在同一个进程中的组件是属于同一个虚拟机和同一个 Application 的,同理,运行在不同进程中的组件是属于两个不同的虚拟机和 Application 的。
2.3 IPC 基础概念介绍
IPC 中的一些基础概念,主要包含三方面内容:Serializable
接口,Parcelable
接口以及Binder
。
Serializable
和 Parcelable
接口可以完成对象的序列化过程,当需要通过 Intent
和 Binder
传输数据时就需要用到它们。
当把对象持久化到存储设备上或通过网络传输给其他客户端时,也需要使用 Serializable
来完成对象的持久化。