Android开发中怎样用多进程、用多进程的好处、多进程的缺陷、解决方法

来源:互联网 发布:天刀捏脸数据女刘亦菲 编辑:程序博客网 时间:2024/06/07 02:23

1.怎样用多进程

Android多进程概念:一般情况下,一个应用程序就是一个进程,这个进程名称就是应用程序包名。我们知道进程是系统分配资源和调度的基本单位,所以每个进程都有自己独立的
资源和内存空间,别的进程是不能任意访问其他进程的内存和资源的。
如何让自己的应用拥有多个进程:
四大组件在AndroidManifest文件中注册的时候,有个属性android:process这里可以指定组件的所处的进程。
默认就是应用的主进程。指定为别的进程之后,系统在启动这个组件的时候,就先创建(如果还没创建的话)这个进程,然后再创建该组件。打印出它的进程名称:重
载Application类的onCreate方法即可。
设置android:process属性,要注意:如果是android:process=”:deamon”,以:开头的名字,表示这是一个应用程序的私有进程,否则它是一个全局进程。私有进程的进程名称是
会在冒号前自动加上包名,而全局进程则不会。一般我们都是有私有进程,很少使用全局进程。

2.用多进程的好处

好处:
(1)分担主进程的内存压力。
当应用越做越大,内存越来越多,将一些独立的组件放到不同的进程,它就不占用主进程的内存空间了。当然还有其他好处,有心人会发现
(2)使应用常驻后台,防止主进程被杀守护进程,守护进程和主进程之间相互监视,有一方被杀就重新启动它。
Android后台进程里有很多应用是多个进程的,因为它们要常驻后台,特别是即时通讯或者社交应用,不过现在多进程已经被用烂了。
典型用法是在启动一个不可见的轻量级私有进程,在后台收发消息,或者做一些耗时的事情,或者开机启动这个进程,然后做监听等。

坏处:消耗用户的电量。
多占用了系统的空间,若所有应用都这样占用,系统内存很容易占满而导致卡顿。
应用程序架构会变得复杂,因为要处理多进程之间的通信。这里又是另外一个问题了。

3.多进程的缺陷
进程间的内存空间是不可见的。开启多进程后,会引发以下问题:
1)Application的多次重建。
2)静态成员的失效。
3)文件共享问题。
4)断点调试问题。

4.解决方法

遇到一个大坑,就是我的APP 的Application 的onCreate方法,竟然执行了好几次,这就导致我在onCreate里面做了一些初始化的操作被重复执行了,导致奇怪的bug产生。后来冷静下来分析一下,才发现有一些第三方组件,比如百度推送之类的,它们是单独开了一个进程,那么每个进程会自己初始化自己的Application,那自然onCreate方法会多次执行。

准确的说就是你的APP里有多少个进程,就会初始化多少次Application 。

但是有的东西就是只需要在Application 的onCreate 里只初始化一次。那怎么解决呢?看代码:

public class MyApplication extends Application {      private final static String PROCESS_NAME = "com.test";      private static MyApplication myApplication = null;      public static MyApplication getApplication() {          return myApplication;      }      /**      * 判断是不是UI主进程,因为有些东西只能在UI主进程初始化      */      public static boolean isAppMainProcess() {          try {              int pid = android.os.Process.myPid();              String process = getAppNameByPID(MyApplication.getApplication(), pid);              if (TextUtils.isEmpty(process)) {                  return true;              } else if (PROCESS_NAME.equalsIgnoreCase(process)) {                  return true;              } else {                  return false;              }          } catch (Exception e) {              e.printStackTrace();              return true;          }      }      /**      * 根据Pid得到进程名      */      public static String getAppNameByPID(Context context, int pid) {          ActivityManager manager = (ActivityManager)                   context.getSystemService(Context.ACTIVITY_SERVICE);          for (android.app.ActivityManager.RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {              if (processInfo.pid == pid) {                  return processInfo.processName;              }          }          return "";      }      @Override      public void onCreate() {          super.onCreate();          myApplication = this;          if (isAppMainProcess()) {              //do something for init          }      }  }  

这样就保证了可以只初始化一次。

2)针对静态成员的失效:
使用Intent或者aidl等进程通讯方式传递内容,不能用静态或单例模式。
3)针对文件共享问题:
多进程情况下会出现两个进程在同一时刻访问同一个数据库文件的情况。这就可能造成资源的竞争访问,导致诸如数据库损坏、数据丢失等。在多线程的情况下我们有锁机制控制资源的共享,但是在多进程中比较难,虽然有文件锁、排队等机制,但是在Android里很难实现。解决办法就是多进程的时候不并发访问同一个文件,比如子进程涉及到操作数据库,就可以考虑调用主进程进行数据库的操作。
4)针对断点调试问题:
调试就是跟踪程序运行过程中的堆栈信息,由于每个进程都有自己独立的内存空间和各自的堆栈,无法实现在不同的进程间调试。因此要改为同一进程:调试时去掉AndroidManifest.xml中android:process标签,这样保证调试状态下是在同一进程中,堆栈信息是连贯的。待调试完成后,再将标签复原。

原创粉丝点击