小议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;
}
分别在自己的进程中初始化
小议Android多进程以致Application多次初始化的更多相关文章
- 【转】Android多进程总结一:生成多进程(android:process属性)
前言 正常情况下,一个apk启动后只会运行在一个进程中,其进程名为apk的包名,所有的组件都会在这个进程中运行,以下为DDMS的进程截屏: com.biyou.multiprocess为进程名,也是a ...
- 【转】 Android自定义捕获Application全局异常
大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程序安装到某款手机上说不定就出现崩溃的现象,开发者个人不可能购买所有设备逐个调试,所以在程序发布出去之后,如果出现了 ...
- Android 多进程编程 15问15答!
ps:阅读本文 需要对android 多进程编程有一定了解. 1.Android中总共有几种方式进行IPC? 答:一共有两种,一种是binder 还有一种是socket.Binder 大家用的比较多. ...
- Android(java)学习笔记120:Android中的Application类用法
1.简介 如果想在整个应用中使用全局变量,在java中一般是使用静态变量,public类型:而在android中如果使用这样的全局变量就不符合Android的框架架构,但是可以使用一种更优雅的方式就是 ...
- Android(java)学习笔记61:Android中的 Application类用法
1. 简介 如果想在整个应用中使用全局变量,在java中一般是使用静态变量,public类型:而在android中如果使用这样的全局变量就不符合Android的框架架构,但是可以使用一种更优雅的方式就 ...
- 关于jni编译32位、64位动态库(Android.mk和Application.mk文件)
最近新项目需要编译64位的动态库,这里记录如何配置. 在jni目录下加入Android.mk和Application.mk文件. Application.mk APP_ABI := armeabi a ...
- 利用Android多进程机制来分割组件
android对于内存有一定的限制,很多手机上对内存的限制是完全不同的.我们的应用程序其实就是一个进程,这个进程是完全独立的,这个进程分配的内存是一定的,所以我们经常会遇到OOM的问题.但,你可能不知 ...
- 在Ubuntu上为Android系统的Application Frameworks层增加硬件访问服务(老罗学习笔记5)
在数字科技日新月异的今天,软件和硬件的完美结合,造就了智能移动设备的流行.今天大家对iOS和Android系统的趋之若鹜,一定程度上是由于这两个系统上有着丰富多彩的各种应用软件.因此,软件和硬件的关系 ...
- 在Ubuntu上为Android系统的Application Frameworks层增加硬件访问服务
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6578352 在数字科技日新月异的今天,软件和硬 ...
随机推荐
- canvas基本图形
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- java安装以及jdk和jre安装(简单了解)
轻松了解JDK是什么 什么是jdk? JDK是学好Java的第一步.不管是你要学习java编程,还是要搭建jsp web开发环境,或者是android开发环境都离不开它. jdk是什么呢?jdk的是j ...
- [luoguP3325][HNOI2012]矿场搭建
P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...
- javascript操作Date对象
Date 对象用于处理日期和时间. 创建 Date 对象的语法: var myDate=new Date() Date 对象会自动把当前日期和时间保存为其初始值. 参数形式有以下5种: new Dat ...
- 在Azure上部署Sqlserver网络访问不了的问题
最近在部署Azure虚拟机的时候,一直访问不了网络数据库,一搜资料才知道,Azure默认是不打开入网规则的,需要手动设置. 在 Windows 防火墙中为数据库引擎的默认实例打开 TCP 端口 在“开 ...
- 轻量ORM-SqlRepoEx 重大升级
.Net平台下兼容.NET Standard 2.0,一个实现以Lambda表达式转转换标准SQL语句,支持MySQL.SQL Server数据库方言,使用强类型操作数据的轻量级ORM工具,在减少魔法 ...
- Oracle之视图
Oracle之视图 2018.9.12 由于视图的数据与表数据互相关联,所以切记谨慎操作 建立视图 使用下面sql语句来完成视图的创建 create or replace view 视图名 as se ...
- 微信小程序腾讯云配置Tomcat https端口
在个人开发微信小程序时,发布之前要配置微信小程序的域名https及域名的SSL证书的申请及安装 我用的是腾讯云,SSL证书申请好之后,点击下载,解压文件夹,会有如图,根据你要配置的服务器是哪种,我是t ...
- eventlet详解
正真工作才发现很懒,没这么多时间写文,毕竟小白,参照大神写的,不喜勿喷 1.eventlet是什么eventlet - 具有WSGI支持的异步框架eventlet是python库函数,一个是处理和网络 ...
- Nginx反向代理 Laravel获取真实IP地址(PHP)
使用VUE前后端分离开发 后端使用Laravel 想要获取到用户的真实IP地址 因为分离开发不同源跨域问题 所以只能进行前端Nginx反向代理 location /api { rewrite ^/a ...