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包名+冒号+后面的名字
<activity android:name=".TestActivity"
            android:process=":com.gaode.map"/>
  • 如果小写字母以:开头 比如"com.baidu.map"
    该组件将运行在以这个名字命名的进程中
    这种方式就可以让不同应用中的组件可以共享一个进程
<activity android:name=".TestActivity"
            android:process="com.baidu.map"/>

示例:

<activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

        <activity android:name=".TestActivity"
            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再次初始化

onCreate执行多次

底层原理参考:http://gityuan.com/2016/03/26/app-process-create/

如何避免Application多次初始化

上面的代码已经给出了解决方法,就是判断当前进程是不是主进程
若不是可以跳过主进程的初始化
可以参考文章:https://blog.csdn.net/sz_chrome/article/details/72911392

多进程的好处

常驻后台任务应用

核心后台服务模块和其他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思想,提供服务,
接口调用,避免直接去访问对方进程的文件或者数据库,提升设计美感,
同时也能提升代码的稳定性

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,565评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,021评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,003评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,015评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,020评论 5 370
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,856评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,178评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,824评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,264评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,788评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,913评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,535评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,130评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,102评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,334评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,298评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,622评论 2 343

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,488评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,691评论 2 59
  • 面试必背 会舍弃、总结概括——根据我这些年面试和看面试题搜集过来的知识点汇总而来 建议根据我的写的面试应对思路中的...
    luoyangzk阅读 6,743评论 6 173
  • 1 邂逅“猫掌柜” 秋日的午后,阳光暖暖的。 在公司吃了午饭,小小习惯到楼下的“猫掌柜”坐一坐。找一个靠窗的角...
    简_豆妈阅读 875评论 4 2
  • 时光静静的想念,我在顿河边等待,也许是真的你不会来,但是我会一直一直一个人默守,许多事情不要说,一个眼神交流就够了...
    不留心阅读 496评论 2 6