Android应用开发Android 多进程开发教程
白羽 2019-03-04 来源 :网络 阅读 659 评论 0

摘要:本文将带你了解Android应用开发Android 多进程开发教程,希望本文对大家学Android有所帮助。

    本文将带你了解Android应用开发Android 多进程开发教程,希望本文对大家学Android有所帮助。



Android应用开发Android 多进程开发教程


前言
   
      正常情况下,一个apk启动后只会运行在一个进程中,其进程名为AndroidManifest.xml文件中指定的应用包名,所有的基本组件都会在这个进程中运行。但是如果需要将某些组件(如Service、Activity等)运行在单独的进程中,就需要用到android:process属性了。我们可以为android的基础组件指定process属性来指定它们运行在指定进程中。android使用多进程重构项目架构,可以分担主进程压力以免因资源消耗过大被crash掉,另外多进程相互监听唤醒,可以使应用程序长期驻守后台接受即时消息和通知,防止应用被系统回收。下面就总结一下多进程开发的经验及优化。
   
    一、多进程概念
   
      一般情况下,一个应用程序就是一个进程,这个进程名称就是应用程序包名。我们知道进程是系统分配资源和调度的基本单位,所以每个进程都有自己独立的资源和内存空间,别的进程是不能任意访问其他进程的内存和资源的。
   
     
   
    二、多进程机制
   
     
   
    四大组件在AndroidManifest文件中注册的时候,有个属性android:process这里可以指定组件的所处的进程。
   
    对process属性的设置有两种形式:
   
     
   
      第一种形式:如android:process=:remote,以冒号开头,冒号后面的字符串原则上是可以随意指定的。如果我们的包名为“com.example.processtest”,则实际的进程名为“com.example.processtest:remote”。这种设置形式表示该进程为当前应用的私有进程,其他应用的组件不可以和它跑在同一个进程中。
   
    第二种形式:如android:process=com.example.processtest.remote,以小写字母开头,表示运行在一个以这个名字命名的全局进程中,其他应用通过设置相同的ShareUID可以和它跑在同一个进程。
   
      下面通过一个例子来进行一下验证。我们定义两个类:ProcessTestActivity和ProcessTestService,然后在AndroidManifest.xml文件中增加这两个类,并为我们的Service指定一个process属性,代码如下:

    运行代码,通过DDMS进行观察
   
    \
   
      我们可以看到两个进程,名字分别是“com.example.processtest”和“com.example.processtest:remote”,进程ID分别为2722和2739。
   
      ProcessTestService运行在一个单独的私有进程中,如果想让ProcessTestService运行在一个全局进程中,那么只需修改android:process=com.example.processtest.remote即可。Android为每一个应用程序分配了一个独立的虚拟机,或者说为每个进程都分配了一个独立的虚拟机,不同的虚拟机在内存分配上   有不同的地址空间,这就会导致在不同的虚拟机中访问同一类的对象会产生多份副本。在一个进程中修改某个值只会影响当前进程,对其他进程不会造成任何影响。
   
    三、多进程优点
   
    一般来说,Android应用多进程有三个好处:
   
      1)我们知道Android系统对每个应用进程的内存占用是有限制的,而且占用内存越大的进程,通常被系统杀死的可能性越大。让一个组件运行在单独的进程中,可以减少主进程所占用的内存,降低被系统杀死的概率.
   
    2)如果子进程因为某种原因崩溃了,不会直接导致主程序的崩溃,可以降低我们程序的崩溃率。
   
    3)即使主进程退出了,我们的子进程仍然可以继续工作,假设子进程是推送服务,在主进程退出的情况下,仍然能够保证用户可以收到推送消息。
   
    四、多进程缺点
   
      我们已经开启了应用内多进程,那么,开启多进程是不是只是我们看到的这么简单呢?其实这里面会有一些陷阱,稍微不注意就会陷入其中。我们首先要明确的一点是进程间的内存空间时不可见的。
   
    从而,开启多进程后,我们需要面临这样几个问题:
   
    1)Application的多次重建。运行在同一个进程中的组件是属于同一个虚拟机和同一个Application的,运行在不同进程中的组件是属于两个不同的虚拟机和Application的。
   
    2)静态成员和单例模式完全失效。
   
    3)文件共享问题。比如SharedPreferences 的可靠性下降。
   
    4)断点调试问题。
   
    1、Application的多次重建
   
    我们先通过一个简单的例子来看一下第一种情况。
   
      Manifest文件如上面提到的,定义了两个类:ProcessTestActivity和ProcessTestService,我们只是在Activity的onCreate方法中直接启动了该Service,同时,我们自定义了自己的Application类。代码如下:
   

    public class MyApplication extends Application {
        public static final String TAG =   viclee;
        @Override
        public void onCreate() {
            super.onCreate();
            int pid =   android.os.Process.myPid();
            Log.d(TAG, MyApplication   onCreate);
            Log.d(TAG, MyApplication pid   is  + pid);
        }
    }

    public class ProcessTestActivity extends Activity {
        public final static String TAG =   viclee;
      
        @Override
        protected void onCreate(Bundle   savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_process_test);
      
            Log.i(TAG,   ProcessTestActivity onCreate);
            this.startService(new   Intent(this, ProcessTestService.class));
        }
    }

    public class ProcessTestService extends Service {
        public static final String TAG =   viclee;
      
        @Override
        public void onCreate() {
            Log.i(TAG, ProcessTestService   onCreate);
        }
      
        @Override
        public IBinder onBind(Intent   arg0) {
            return null;
        }
      
    }
    执行上面这段代码,查看打印信息:
    \
   
      我们发现MyApplication的onCreate方法调用了两次,分别是在启动ProcessTestActivity和ProcessTestService的时候,而且我们发现打印出来的pid也不相同。由于通常会在Application的onCreate方法中做一些全局的初始化操作,它被初始化多次是完全没有必要的。出现这种情况,是由于即使是通过指定process属性启动新进程的情况下,系统也会新建一个独立的虚拟机,自然需要重新初始化一遍Application。那么怎么来解决这个问题呢?
   
    我们可以通过在自定义的Application中通过进程名来区分当前是哪个进程,然后单独进行相应的逻辑处理。


    public class MyApplication extends Application {
        public static final String TAG =   viclee;
      
        @Override
        public void onCreate() {
            super.onCreate();
            int pid =   android.os.Process.myPid();
            Log.d(TAG, MyApplication   onCreate);
            Log.d(TAG, MyApplication pid   is  + pid);
      
            ActivityManager am =   (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
            List runningApps =   am.getRunningAppProcesses();
            if (runningApps != null   && !runningApps.isEmpty()) {
                for   (ActivityManager.RunningAppProcessInfo procInfo : runningApps) {
                    if (procInfo.pid ==   pid) {
                         if   (procInfo.processName.equals(com.example.processtest)) {
                             Log.d(TAG,   process name is  +   procInfo.processName);
                         } else if   (procInfo.processName.equals(com.example.processtest:remote)) {
                             Log.d(TAG,   process name is  +   procInfo.processName);
                         }
                    }
                }
            }
        }
    }
    运行之后,查看Log信息:
   
    \
   
    图中可以看出,不同的进程执行了不同的代码逻辑,可以通过这种方式来区分不同的进程需要完成的初始化工作。
   
    2、静态变量和单例模式完全失效
   
    下面我们来看第二个问题,将之前定义的Activity和Service的代码进行简单的修改,代码如下:
   

    public class ProcessTestActivity extends Activity {
        public final static String TAG =   viclee;
        public static boolean processFlag   = false;
      
        @Override
        protected void onCreate(Bundle   savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_process_test);
      
            processFlag = true;
            Log.i(TAG,   ProcessTestActivity onCreate);
            this.startService(new   Intent(this, ProcessTestService.class));
        }
    }

    public class ProcessTestService extends Service {
        public static final String TAG =   viclee;
      
        @Override
    body{ }   



本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之Android频道!

本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程