1. Android 中开启多进程模式的方式
- 在 Android 中使用多进程只有一种方法:给四大组件在 AndroidMenifest.xml 文件中指定 android:process 属性。除此之外没有其他办法,也就是说我们无法给一个线程或者一个实体类指定其运行时所在的进程
- 还有一种非常规的方法:通过 JNI 在 native 层去 fork 一个新的进程。但这种方法属于特殊情况,也不是常用的创建多进程的方式
2. 指定 android:process 属性的方式及区别
默认进程
- 入口 Activity 没有指定 process 属性,因为它运行在默认进程中,默认进程的进程名是应用的包名
私有进程
android:process=":自定义进程名"
- : 的含义是在当前自定义进程名的前面附加上当前应用的包名,这是一种简写的方法
- 进程名以 : 开头的进程属于当前应用的私有进程,其他应用的组件不可以和它跑在同一个进程中
全局进程
android:process="包名.自定义进程名"
- 这是一种完整的命名方式,不会附加其他信息
- 进程名不以 : 开头的进程属于全局进程,其他应用通过 ShareUID 的方式可以和它跑在同一个进程中
3. 全局进程与 ShareUID 的关系
- Android 系统会为每个应用分配一个唯一的 UID,具有相同 UID 的应用才能共享数据
- 两个应用通过 ShareUID 跑在同一个进程中是有要求的,需要这两个应用有相同的 UID 并且签名相同
- 在这种情况下,它们可以互相访问对方的私有数据,比如 data 目录、组件信息等,不管它们是否跑在同一个进程中
- 如果它们跑在同一个进程中, 那么除了能共享 data 目录、组件信息,还可以共享内存数据,或者说它们看起来就像是一个应用的两个部分
4. Android 多进程模式的运行机制
- 特殊情况下,某些组件之间是不需要共享数据的,此时可以通过直接指定 android:process 的方式来开启多进程。但这种场景是不常见的,几乎所有情况都需要共享数据
- Android 会为每个应用或者说每个进程分配一个独立的虚拟机,不同的虚拟机在内存分配上有不同的地址空间,在不同的虚拟机中访问同一个类的对象会产生多个副本
- 为了解决多进程带来的问题,系统提供了很多跨进程通信的方法,虽然不能直接共享内存,但是通过跨进程通信依然可以实现数据交互
5. 在 Android 中使用多进程可能会导致的问题
静态成员和单例模式完全失效
- Android 会为每个进程分配一个独立的虚拟机,对应独立的内存地址,对应类对象的多个副本
线程同步机制完全失效
- 本质也是因为独立的虚拟机,既然都不是同一块内存了,那么不管是锁对象还是锁全局类都无法保证线程同步,因为不同进程锁的不是同一个对象
SharedPreferences 的可靠性下降
- SharedPreferences 不支持两个进程同时去执行写操作,否则会导致一定几率的数据丢失
- 因为 SharedPreferences 底层是通过读写 XML 文件来实现的,并发写显然是可能出问题的,甚至并发读写都有可能出问题
Application 会多次创建
- 当一个组件跑在一个新的进程中的时候,由于系统要在创建新的进程的同时分配独立的虚拟机,所以这个过程其实就是启动一个应用的过程。因此,相当于系统又把这个应用重新启动了一遍,既然重新启动了,那么自然会创建新的 Application
- 运行在同一个进程中的组件是属于同一个虚拟机和同一个 Application 的,同理,运行在不同进程中的组件是属于两个不同的虚拟机和 Application 的
- 在多进程模式中,不同进程的组件会拥有独立的虚拟机、Application 和内存空间