最近遇到一个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;
}

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

最新文章

  1. win10电脑优化
  2. SQL Server 堆表行存储大小(Record Size)
  3. Media Queries详解
  4. SQL Server 百万级数据提高查询速度的方法
  5. 关于header(&#39;location:url&#39;)的一些说明,php缓冲区
  6. bash 统计文件行数
  7. ASP.NET的六种验证控件的使用
  8. 转: sublime text 2 前端编码神器-快捷键与使用技巧介绍
  9. ensp实战之防火墙安全转发策略
  10. 【hihoCoder】#1039 : 字符消除 by C solution
  11. Chinese Rings
  12. CynosDB技术详解——架构设计
  13. Windows 虚拟机 忘记密码的处理
  14. GitHub 托管的10款免费开源 windows 工具
  15. Fabric的权限管理:Attribute-Based Access Control
  16. [Machine Learning] some concept about the CV
  17. Daily Scrumming* 2015.12.21(Day 13)
  18. 九:python 对象类型详解五:元组
  19. 正则表达式sed
  20. ItemsControl

热门文章

  1. 关于java中Exception异常
  2. js 实现div跟随鼠标移动
  3. 【luogu P3385 负环】 模板
  4. 【luogu P2731 骑马修栅栏】 题解
  5. ORA-01950:对表空间 &#39;USERS&#39; 无权限
  6. oracle client安装与配置
  7. JS数组去重的十种方法(转载)
  8. SPOJ8222 NSUBSTR - Substrings(后缀自动机)
  9. A^B Mod C (51Nod - 1046 )(快速幂)
  10. ABAP术语-EDI (Electronic Data Interchange)