目录
- 如何开启多进程?
- 理解多进程模式的运行机制
如何开启多进程?
给四大组件在androidMenifest中指定android:precess
<activity
android:name=".ThreeActivity"
android:exported="false"
android:process="com.my.process.three.remote" />
<activity
android:name=".TwoActivity"
android:exported="false"
android:process=":remote" />
<activity
android: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 {
@Override
public 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;
}
}
}
}
// 如果未找到,返回null
return null;
}
}
MyApplication 运行了三次。