android webview 单例,Android Application是单例,正确吗?

Android 中Application是单例,这个问题可能大家会毫不犹豫的回答正确

但是,如果APP中如果有集成一些第三方SDK的

并且在Application中加了打印的可能就会发现,APP启动的时候

怎么onCreate中的打印走了多次

不是说Application只会实例化一次的吗?

因为onCreate走了多次,说明创建了多个

那这个问题答案应该明朗了,在某种情况下,Application不唯一了

那这种情况是什么情况呢?

答案是:多进程

一般我们开发可能极少,除非一些特别的APP,可能我们都不会指定多进程

那为啥集成了第三方SDK会出现这种情况呢

是因为有些SDK指定了组件运行在特别的进程

那为啥第三方SDK会使用多进程?多进程带来的好处是什么?又有什么坏处呢?

进程

Android系统是底层是由Linux改造而来的

进程系统也是一致的,进程,就是程序的具体实现

当程序第一次启动,Android会启动一个Linux进程(具体由Zygote fork出来)和一个主线程

默认的情况下,所有组件都将运行在该进程内

同一个应用由系统分配一个独立的Linux账户,应用的产生的所有进程,都会是这同一个Linux账户

多进程Application会创建多个

很明显带来的问题就是Application的onCreate方法会执行多次

如果在onCreate方法中,做了初始化的操作,将会导致多次初始化操作

如果是启动的时候就执行的,将会导致启动时间延长

将组件指定在单独的进程

指定多进程是在AndroidManifest.xml里面配置

Android四大组件activity,service,provider, receiver

可以通过android:process属性来指定运行所在的进程

不指定默认就是运行在系统分配的进程

也可以修改默认进程 设置Application的android:process属性,来设置所有组件的默认进程

进程名分两种:

如果以冒号开头,比如":com.gaode.map"

这种情况下,是该APP私有的,进程名是APP包名+冒号+后面的名字

android:process=":com.gaode.map"/>

如果小写字母以:开头 比如"com.baidu.map"

该组件将运行在以这个名字命名的进程中

这种方式就可以让不同应用中的组件可以共享一个进程

android:process="com.baidu.map"/>

示例:

android:process="com.baidu.map"/>

Application 完整代码

public class BaseApplication extends Application {

private static final String APP_NAME = "com.qingguoguo.baseapp";

@Override

public void onCreate() {

super.onCreate();

Log.e("BaseApplication", "onCreate");

Log.e("BaseApplication", getProcessNameByPID(getApplicationContext(), android.os.Process.myPid()));

DBConfig.initGreenDao(this);

}

/**

* 判断是否是主进程

* @return

*/

public boolean isAppMainProcess() {

try {

int pid = android.os.Process.myPid();

String process = getProcessNameByPID(getApplicationContext(), pid);

return TextUtils.isEmpty(process) || APP_NAME.equalsIgnoreCase(process);

} catch (Exception e) {

return true;

}

}

/**

* 根据 pid 获取进程名

* @param context

* @param pid

* @return

*/

public String getProcessNameByPID(Context context, int pid) {

ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

if (manager == null) {

return "";

}

for (android.app.ActivityManager.RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {

if (processInfo == null) {

continue;

}

if (processInfo.pid == pid) {

return processInfo.processName;

}

}

return "";

}

}

在ManinActivity中的点击 事件跳转到TestActivity,将会导致Application再次初始化

10711bf805e5

onCreate执行多次

如何避免Application多次初始化

多进程的好处

常驻后台任务应用

核心后台服务模块和其他UI模块进行分离,保证应用能更稳定的提供服务

从而提升用户体验

解决OOM问题

吃内存的大图,WebView等另开进程,避免主进程OOM

多模块开发

诸如下载服务,监控服务等等另开进程

多进程带来的问题

静态变量和单例模式完全失效

因为进程之间,内存是相互独立的,所以VM方法区的静态变量

也都是独立的,单例模式基于静态变量,所以单例也会失效

在两个不同进程访问一个相同类的静态变量,值未必相同

线程同步机制完全失效

Java的同步机制是VM来进行调度的,两个进程拥有两个不同的VM

所以,同步也会在多进程环境下失效,Synchronized,volatile关键字

等都是基于VM级别的同步,所以不要跨进程去使用线程同步,比如

主进程有个生产者,子进程的消费者是无法正常使用消费功能的,

只能通过跨进程通信,让主进程的消费者去消费,然后再回调

Application会多次创建

每个新进程在创建的时候,都会新建一个Application,所以多进程还

会导致Application多次创建的问题,onCreate方法会多次调用,一般

我们都会在onCreate里初始化操作,那么会多次初始化,最好也不要在

Application中设置过多的静态变量,导致内存增加

文件读写并发访问的问题

文件指的泛指所有需要并发访问的文件,例如:本地文件,数据库文件,

sharepreference等。由于Java中,文件锁、队列机制都是VM级别的,

所以不同进程访问同一个文件锁是不管用的。(通过C++可以实现多进程

文件锁机制,不过不在文本讨论范围内。)所以在实际开发过程中,还是

避免多进程同时访问统一文件,多利用Android中IPC的C/S思想,提供服务,

接口调用,避免直接去访问对方进程的文件或者数据库,提升设计美感,

同时也能提升代码的稳定性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值