zoukankan      html  css  js  c++  java
  • 小议Android多进程以致Application多次初始化

    最近遇到一个bug,当应用加了多进程后,比如总共进程数为N,会出现在`startService()`时`onStartCommand()`方法会被重复调用`(N-1)`次的奇怪现象。

    ***
    ## 祸起
    >最近遇到两个模块互不相干却受到影响的奇怪问题,一个push模块和一个DaemonProcess模块在一起后,会出现如下现像的问题
    ***
    当DaemonProcess为应用加了多进程后,比如总共进程数为N,会出现push模块在`startService()`时`onStartCommand()`方法会被重复调用`(N-1)`次的奇怪现象。
    ***


    ## 寻踪

    * 因为我们用的是Jpush的原因,一开始以为是Jpush,但最后发现是因为引用多进程的原因
    * 再寻找下去发现 调用一次`startService()`时`onStartCommand()`运行多次
    * 而这两者有何关系呢


    ## 举证

    > Demo测试:
    > 首先在Application中申明四个service,其中`ServiceA`和`ServiceC`都各自另开一个进程,`ServiceB`和`ServiceD`都在主进程中,AndroidManifest.xml如下:

    ```

    <service android:name=".ServiceA"
    android:process="com.hujiang.test.servicea"
    android:exported="true"/>

    <service android:name=".ServiceB"
    android:exported="false"/>

    <service android:name=".ServiceC"
    android:process="com.hujiang.test.servicec"
    android:exported="true"/>

    <service android:name=".ServiceD"
    android:exported="false"/>

    ```

    此时在Application中启动四个Service
    ```

    startService(new Intent(this, ServiceA.class));
    startService(new Intent(this, ServiceB.class));
    startService(new Intent(this, ServiceC.class));
    startService(new Intent(this, ServiceD.class));

    ```
    同时各Service打下如下log:

    ```
    public static final String TAG = ServiceB.class.getSimpleName();
    @Override
    public void onCreate() {
    super.onCreate();
    Log.i(TAG,"onCreate" + "pid:" + android.os.Process.myPid());
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    Log.i(TAG,"onStartCommand" + "pid:" + android.os.Process.myPid());
    return super.onStartCommand(intent, flags, startId);
    }

    ```

    在log中会发现
    `onCreate()`方法各执行一遍,这个是正常的,但`onStartCommand()`方法目前执行了三遍,因为共3个进程。

    ## 真相

    1. N个进程,N个独立的虚拟机,Application被N次初使化
    2. 处理时应该在Application中分进程初始化数据


    <!--more-->
    ## 剑谱


    如下解决方案

    mProcessName = getCurrentProcessName(this);
    Log.i(TAG, "onCreate" + "getProcessName:" + mProcessName);
    Log.i(TAG, "init_all_process");
    if(TextUtils.equals(mProcessName, getPackageName())){
    Log.i(TAG, "init_main_process");
    } else if(TextUtils.equals(getProcessName(this, android.os.Process.myPid()), "com.hujiang.test.servicea")){
    Log.i(TAG, "init_a_process");
    }else if(TextUtils.equals(getProcessName(this, android.os.Process.myPid()), "com.hujiang.test.servicec")){
    Log.i(TAG, "init_c_process");
    }

    获取当前进程名称:


    private String getCurrentProcessName(Context context) {
    int pid = android.os.Process.myPid();
    ActivityManager mActivityManager = (ActivityManager) context
    .getSystemService(Context.ACTIVITY_SERVICE);
    for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager
    .getRunningAppProcesses()) {
    if (appProcess.pid == pid) {
    return appProcess.processName;
    }
    }
    return null;
    }


    分别在自己的进程中初始化

  • 相关阅读:
    ABP PUT、DELETE请求错误405.0
    Visual Studio Code 通过 Chrome插件Type Script断点调试Angular 2
    Angular 报错 Can't bind to 'formGroup' since it isn't a known property of 'form'
    ABP 用swagger UI测试API报401无权限访问问题
    ABP .Net Core API和Angular前端APP集成部署
    ABP .Net Core API和Angular前端APP独立部署跨域问题(No Access-Control-Allow-Origin)
    Hosts文件实际应用 配置内部服务器提高访问效率和速度
    mysql-proxy实现读写分离
    mysql主从复制-linux版本
    nginx作反向代理,实现负载均衡
  • 原文地址:https://www.cnblogs.com/renkangke/p/4646841.html
Copyright © 2011-2022 走看看