Android多进程模式

来源:互联网 发布:森系服装品牌 知乎 编辑:程序博客网 时间:2024/06/05 15:07

Android多进程模式

深入理解下android多进程模式,为后续进程间通讯做个铺垫~

进程可以理解为一个应用,一个进程可以只有一个线程,即主线程,android中称为UI线程,在UI线程中才能操作view控件;通过给四大组件指定android:process可以轻松启动一个新的进程,看似简单却隐藏了不少问题

一、开启多进程

在android中使用多进程只有一种方法,那就是给四大组件(Activity、Service、Receiver、ContentProvider)在AndroidManifest中指定android:process属性,也就是无法给一个线程或者一个实体类指定运行所在的进程。(通过JNI在native层fock一个新进场的方式除外)

来看一个简单的例子:
注册页面SecondActivity和ThirdActivity,并设置android:process属性,如下:

这里写图片描述

在MainActivity中启动SecondActivity和ThirdActivity,然后使用add shell ps|grep com.rico.multiprocess可以查看运行的进程:

这里写图片描述

MainActivity没有指定process,默认运行在以包名命名的进程,:remote和com.rico.multiprocess.remote有区别吗?

首先“:”的含义是在当前进程名前附加包名,这是一种简写方式,对于SecondActivity来说,它的完整进程名是:com.rico.multiprocess:remote。其次,进程名以“:”开头属于当前应用的私有进程,其它应用的组件不可以和它跑在同一个进程中,而不以“:”开头的进程属于全局进程,其它应用可以通过shareUID方式和它跑在同一进程中。

二、运行机制

为什么说多进程运行起来会遇到各种奇怪的问题?

public class AppConfig {  public static boolean isDebug = false;}

假设在MainActivity中赋值AppConfig.isDebug = true,然后启动SecondActivity,这是在SecondActivity中打印出来的isDebug是true还是false呢?按照正常逻辑,静态变量在整个程序生命周期内都是生效的,一处修改处处共享,也就是SecondActivity中打印的isDebug应该是true才对,结果却相反:

07-22 21:44:27.494 15138-15138/com.rico.multiprocess I/System.out: MainActivity isDebug->true07-22 21:44:27.682 15190-15190/com.rico.multiprocess:remote I/System.out: SecondActivity isDebug->false

上述问题的原因是SecondActivity运行在单独的进程中,android为每一个应用分配一个独立的虚拟机,或者说为每一个进程分配了一个独立的虚拟机,每个虚拟机在内存分配上有不同的地址空间,这就导致在不同虚拟机上访问的类的对象会产生多个副本。也就是AppConfig在不同进程中存在多个副本,修改com.rico.multiprocess进程的AppConfig不会影响到com.rico.multiprocess:remote进程的AppConfig.

通常使用多进程会有如下问题:
(1)静态成员和单例模式完全失效
(2)线程同步失效
(3)SharePreferences的可靠性下降
(4)Application会多次创建

(1)和(2)的很好理解,因为不是同一个类,(3)是因为sharepreference不支持多进程同时执行写操作,否则会导致一定概率数据丢失,因为sharepreference底层通过读写xml实现,并发写显然容易出问题,(4)可以测试下,在Application加入log

public class MyApplication extends Application{  @Override public void onCreate() {    super.onCreate();    int pid = android.os.Process.myPid();    String processName = "";    ActivityManager manager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);    for (ActivityManager.RunningAppProcessInfo process: manager.getRunningAppProcesses()) {      if(process.pid == pid)      {        processName = process.processName;      }    }    System.out.println("processName->"+processName);  }}

运行一下,发现每一个进程都启动了一次MyApplicaon

07-22 22:04:07.958 32549-32549/com.rico.multiprocess I/System.out: processName->com.rico.multiprocess07-22 22:04:08.374 32584-32584/com.rico.multiprocess:remote I/System.out: processName->com.rico.multiprocess:remote07-22 22:04:08.588 32619-32619/? I/System.out: processName->com.rico.multiprocess.remote

为了解决多进程带来的问题,系统提供了很多跨进程的通讯方式,比如Intent、共享文件、SharePreferences,基于binder的Messager和AIDL以及socket等,binder的通讯机制可以参考下一遍博客:Android Binder通讯机制


参考书籍 —【Android开发艺术探索】

原创粉丝点击