目录
- 如何开启多进程?
- 理解多进程模式的运行机制
如何开启多进程?
给四大组件在androidMenifest中指定android:precess
<activityandroid:name=".ThreeActivity"android:exported="false"android:process="com.my.process.three.remote" /><activityandroid:name=".TwoActivity"android:exported="false"android:process=":remote" /><activityandroid:name=".OneActivity"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity>
打开OneActivity、TwoActivity、ThreeActivity三个界面,查看进程id(在android studio中的device explorer),如下。
:remote与com.my.process.three.remote的区别。
:remote 在当前进程名前面附加当前的包名,简写的方式。com.my.process.three.remote 完整的命名方式。进程名以“:”开头的进程属于当前应用的私有进程,其他应用的组件不可以和它跑在同一个进程中,而进程名不以“:”开头的进程属于全局进程,其他应用通过ShareUID方式可以和它跑在同一进程中。
两个应用通过ShareUID跑在同一个进程,需要有相同的ShareUID和签名才可以。 |
---|
理解多进程模式的运行机制
增加一个类BOOK,并添加静态变量id。
public class Book {public static int id = 1;
}
在OneActivity中将id置位2,打印id,然后启动TwoActivity,再打印id。
一般情况下,静态变量是可以在所有的地方共享的,且一处修改处处都会同步。看上图,TwoActivity应该是2才对,但显示是1,这是多进程带来的问题。
android为每个进程都分配一个独立的虚拟机,不同的虚拟机在内存上有不同的地址空间,导致在不同的虚拟机中访问同一个类的对象会产生多份副本。结合本例,com.jn.testbrodercast与:remote进程都存在一个Book类,互不干扰,在一个进程中修改id只会影响当前进程。这就是为什么在OneActivity置位2,在TwoActivity不会受到影响的原音。
多进程会造成的问题:
- 静态成员和单例模式完全失效
- 线程同步机制完全失效
- sharedpreferences的可靠性下降
- Application会创建多次
第1个问题上面说明了,第二问题就是多个独立虚拟机,都有各自的锁,不同进程锁的不是同一个对象。第3个问题SharedPreferences不支持两个进程同时去执行写操作。第4个问题,但一个组件跑在一个新的进程中的时候,系统要创建新的进程且分配独立虚拟机,这实则是启动了一个应用。
第4点的小实验,添加将下面代码,打开三个activity,查看日志信息。
public class MyApplication extends Application {@Overridepublic void onCreate() {super.onCreate();Log.d("MyApplication", getProcessNameFromPid(Process.myPid()));}public String getProcessNameFromPid(int pid) {// 使用ActivityManager获取进程信息ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);if (manager != null) {List<ActivityManager.RunningAppProcessInfo> processes = manager.getRunningAppProcesses();if (processes != null) {for (ActivityManager.RunningAppProcessInfo process : processes) {if (process.pid == pid) {// 返回进程名称return process.processName;}}}}// 如果未找到,返回nullreturn null;}
}
MyApplication 运行了三次。