android控件单例,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?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

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、付费专栏及课程。

余额充值