多进程通信方式以及带来一系列问题

289次阅读  |  发布于3年以前

前言

今天来讲解下:多进程通信方式以及带来的问题,方便在项目中遇到问题及时的处理;

一、Android中多进程详解

1、定义

2、开启多进程

Android中开启多进程只有一种方法,就是在AndroidManifest.xml中注册Service、Activity、Receiver、ContentProvider时指定android:process属性,例如:

<service
    android:name=".MyService"
    android:process=":remote">
</service>
<activity
    android:name=".MyActivity"
    android:process="com.test.remote2">
</activity>

我们为MyService和MyActivity指定的android:process属性值有所不同,它们的区别如下:

3、Android中的多进程通信方式

多进程通信方式主要有以下几种,它们之间各有优缺点,可根据使用场景选择选择:

二、 多进程带来的问题

1、静态变量失效

在一个Activity中新建一个静态变量TEST_STATIC,并在RemoteActivity1中的onStartOtherRemoteActivity方法中自增,之后启动RemoteActivity2,并在2中打印TEST_STATIC的值;


public static int TEST_STATIC = 21;
public void onStartOtherRemoteActivity(View view) {
    TEST_STATIC++;
    Log.e(TAG, "onStartOtherRemoteActivity: " + TEST_STATIC);
    startActivity(new Intent(this, RemoteActivity2.class));
}
结果:
// RemoteActivity1 log
E/RemoteActivity1: onStartOtherRemoteActivity: 22
// RemoteActivity2 log
E/RemoteActivity2: onCreate: 21

2、线程同步机制失效

本质上跟静态变量类似,在一个进程锁住的是副本的对象,而在另一个副本中,内存都不同,所以肯定是无效的;

3、SharedPreferences可靠性下降

4、Application会被创建多次

当一个组件跑在一个新的进程中时,系统给新的进程分配一个新的虚拟机,就相当于应用又一次的重新启动,Application作为应用基础肯定也会被重新创建;

新建Application类,继承自Application,并在onCreate方法中输出当前进程的PID:


public class LApplication extends Application {
    private static final String TAG = "LApplication";
    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, "onCreate: " + android.os.Process.myPid());
    }
}

当依次开启进程后输出如下:

// Main
E/LApplication: onCreate: 16031
// RemoteActivity1
E/LApplication: onCreate: 16127
// RemoteActivity2
E/LApplication: onCreate: 16202

Application被创建多次带来的问题是,有些时候会需要在Application中初始化些依赖,但是多进程就会随着Application的创建而重复初始化,可以在Application中设置一些条件跳过重复初始化部分;

// 根据pid获取进程名
private String getAppName(int pid) {
    String processName = null;
    ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
    List<ActivityManager.RunningAppProcessInfo> list = am.getRunningAppProcesses();
    for (ActivityManager.RunningAppProcessInfo info : list) {
        try {
            if (info.pid == pid) {
                processName = info.processName;
                return processName;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    return null;
}

通过PID获取进程名,与包名做对比,只有跟包名一致时才做一些初始化工作;

总结

多进程实现今天没有讲,以后会讲解的;

多进程不难的,难的在于要克服困难,战胜自己;

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8