android多进程深入分析

来源:互联网 发布:新手c#编程题及答案 编辑:程序博客网 时间:2024/05/16 19:51

android一个应用程序,可以存在多个进程, 在某些场景,比如希望获得更多的内存、希望功能模块间不相互影响,或者彻底解决webview内存泄漏等, 可以开多个进程;

       看似好用且强大的多进程,也是一把双刃剑,今天就深入分析分析多进程;

前提明确一点: 进程间的内存空间是不可见的

       测试项目源码地址


一、简要介绍android多进程的实现

        在Manifest中,可以对Activity、Service、Broadcast receiver、Content Provider 四大组件,通过android:process属性设置独立进程,如下:

<activity android:name="com.tihi.multiprocess.SecActivity"    android:process=":subprocesss"    />
       打开的SecActivity界面,就运行在:subprocesss进程中了


二、下面进行多进程分析


1.  进程间全局静态变量共享吗?

测试验证:在主进程中修改全局静态变量, 在子进程中读取,查看值是修改后的还是修改前的;

                    如果值是修改后的,说明多进程共享全局静态变量,否则 说明不共享


 (1)Manifest中, 声明两个界面,MainActivity 默认运行在主进程,  SecActivity设置运行在独立进程 :subprocesss

<activity android:name="com.tihi.multiprocess.MainActivity">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <activity android:name="com.tihi.multiprocess.SecActivity"            android:process=":subprocesss"            />
(2) 在常量类Consts.java中,定义一个全局静态变量

public class Consts {    /** 静态全局变量 */    public static int num = 0;}

(3)在 MainActivity 中,把全局静态变量 num 设置为 100:

public class MainActivity extends FragmentActivity {    private static final String TAG_PREFIX = "MainActivity";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        ViewUtils.inject(this);        Util.printCurProThr(TAG_PREFIX);        init();    }    /**     * 初始化     */    private void init() {        Consts.num = 100; //在主进程,将全局变量值赋值为100        Logger.log(TAG_PREFIX + ", 全局静态变量值num为:" + Consts.num);    }


(4)MainActivity 界面上,点击按钮,打开SecActivity界面,打印出num的值

private void testStatic(View view) {    Logger.log(TAG_PREFIX + ", 全局静态变量值num为:" + Consts.num);}

结果如下: 子进程的SecActivity界面,打印出的全局变量num值为0,是未修改过的,说明 多进程间不共享全局静态变量,  切记哦,以免出现逻辑不正确;

推测:单例模式也不共享,因为内存不在一块


另外,从上图可以看出, MainActivity  运行的 进程名为com.tihi.multiprocess,即包名, SecActivity运行的进程名为 com.tihi.multiprocess:subprocesss



2.  多进程,Application实例创建一个还是多个?

测试验证:在 Application 类的 onCreate中,打印出当前的进程

public class App extends Application{    private static App _instance;    private static final String TAG_PREFIX = "App";    @Override    public void onCreate() {        super.onCreate();        _instance = this;        Util.printCurProThr(TAG_PREFIX + "_" + hashCode());    }    public static App instance() {        return _instance;    }}

   启动MainActivity,接着在界面上点击按钮,打开SecActivity,日志如下, 打开这两个界面时,分别创建了两个Application 实例, 如果需要针对不同进程区分对待的话,需要在代码中增加进程区分



3, 子进程启动主进程的界面,该界面在哪个进程运行?

测试验证: 有三个界面,MainActivity(主进程)  打开 --> SecActivity(子进程) 打开-->  ThirdActivity(主进程)

日志如下,ThirdActivity界面虽然从子进程打开,但仍然运行在主进程



4,  进程间,可以通过Intent传递参数吗?

测试验证:有两个界面 MainActivity(主进程)   --> SecActivity(子进程), 打开SecActivity界面时使用Intent传递参数


启动SecActivity代码: 传递了 personJson 字符串

public static void startAct(Context context, String personJson) {        Intent intent = new Intent(context, SecActivity.class);        intent.putExtra(INTENT_PENSON_KEY, personJson);        context.startActivity(intent);    }

日志如下: 说明跨进程 可以正确传递intent参数



5, 进程间,SharedPreference 内容共享吗?

测试验证:有两个界面 MainActivity(主进程)   --> SecActivity(子进程), 主进程存储数据到share文件,子进程读取share,测试数据是否是主进程保存的

从日志看出, 子进程从share读取出的值与主进程存入的值是相同的,说明SharedPreference 进程间共享

推测:文件都是共享的,但可能存在进程并发的问题, 不同进程间的线程并发、锁就失效了

另外,进程间可以通过 广播等方式通信



6. 两个app应用(看做两个进程),通过BroadCast Receiver通信

测试验证:A应用发广播,B应用接收广播,并执行相应操作

A应用发送广播代码:

private void testAppBroad(View view) {        Logger.log(TAG_PREFIX + ", Aapp, 发送广播啦");        Intent intent = new Intent(Consts.APP_BROAD_CAST_ACTION);        intent.putExtra(Consts.APP_BROAD_CAST_INTENT_DATA_KEY, "appBroadTest");        sendBroadcast(intent);    }

B应用接收广播代码:

private BroadcastReceiver myReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            Util.printCurProThr("BApp, MainActivity");            if(intent != null) {                String param = intent.getStringExtra(Consts.APP_BROAD_CAST_INTENT_DATA_KEY);                Logger.log("BApp, 动态注册,接收到其他app发过来的广播,传递的值:" + param);            }        }    };
运行后,日志如下: BApp能正常接收广播内容, 广播接收者 的 onReceive运行在 UI主线程, 所以如果有耗时处理, 通过service启子线程去处理,广播声明周期只有10s, 避免ANR;



题外话: EventBus的消息通知,不能跨进程,如需跨进程通知,则请改用BroadCast Receiver;

网上说广播的生命周期只有10s,  但实测30s后都能继续执行,奇怪了

未完待续。。。


总结:

1, 进程间全局静态变量、单例模式 不共享,因为内存不在一块;

2,Application 类,每个进程会创建一个实例, 所以如果有多进程都需要使用的数据,不要放在Application 中;

3,线程的锁、对象锁机制,对多进程的线程无效;

4, 文件虽说是共享的,但多进程同时并发操作会有问题,sharedPreference不支持多进程同时写;

5,断点调试,Eclipse上开发android时,可以同时选择多个进程一起调试, 但Android studio一次只能选择一个进程调试;


0 0
原创粉丝点击