Android Application是單例蛮浑,正確嗎?

Android 中Application是單例只嚣,這個問題可能大家會毫不猶豫的回答正確
但是沮稚,如果APP中如果有集成一些第三方SDK的
并且在Application中加了打印的可能就會發(fā)現(xiàn),APP啟動的時候
怎么onCreate中的打印走了多次
不是說Application只會實例化一次的嗎册舞?

因為onCreate走了多次蕴掏,說明創(chuàng)建了多個
那這個問題答案應(yīng)該明朗了,在某種情況下,Application不唯一了

那這種情況是什么情況呢盛杰?
答案是:多進(jìn)程
一般我們開發(fā)可能極少挽荡,除非一些特別的APP,可能我們都不會指定多進(jìn)程
那為啥集成了第三方SDK會出現(xiàn)這種情況呢
是因為有些SDK指定了組件運(yùn)行在特別的進(jìn)程

那為啥第三方SDK會使用多進(jìn)程即供?多進(jìn)程帶來的好處是什么定拟?又有什么壞處呢?

進(jìn)程

Android系統(tǒng)是底層是由Linux改造而來的
進(jìn)程系統(tǒng)也是一致的逗嫡,進(jìn)程青自,就是程序的具體實現(xiàn)
當(dāng)程序第一次啟動,Android會啟動一個Linux進(jìn)程(具體由Zygote fork出來)和一個主線程
默認(rèn)的情況下祸穷,所有組件都將運(yùn)行在該進(jìn)程內(nèi)
同一個應(yīng)用由系統(tǒng)分配一個獨立的Linux賬戶性穿,應(yīng)用的產(chǎn)生的所有進(jìn)程,都會是這同一個Linux賬戶

多進(jìn)程Application會創(chuàng)建多個

很明顯帶來的問題就是Application的onCreate方法會執(zhí)行多次
如果在onCreate方法中雷滚,做了初始化的操作需曾,將會導(dǎo)致多次初始化操作
如果是啟動的時候就執(zhí)行的,將會導(dǎo)致啟動時間延長

將組件指定在單獨的進(jìn)程

指定多進(jìn)程是在AndroidManifest.xml里面配置
Android四大組件activity祈远,service呆万,provider, receiver
可以通過android:process屬性來指定運(yùn)行所在的進(jìn)程
不指定默認(rèn)就是運(yùn)行在系統(tǒng)分配的進(jìn)程
也可以修改默認(rèn)進(jìn)程 設(shè)置Application的android:process屬性,來設(shè)置所有組件的默認(rèn)進(jìn)程
進(jìn)程名分兩種:

  • 如果以冒號開頭车份,比如":com.gaode.map"
    這種情況下谋减,是該APP私有的,進(jìn)程名是APP包名+冒號+后面的名字
<activity android:name=".TestActivity"
            android:process=":com.gaode.map"/>
  • 如果小寫字母以:開頭 比如"com.baidu.map"
    該組件將運(yùn)行在以這個名字命名的進(jìn)程中
    這種方式就可以讓不同應(yīng)用中的組件可以共享一個進(jìn)程
<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);
    }

    /**
     * 判斷是否是主進(jìn)程
     * @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;
        }
    }

    /**
     * 根據(jù) pid 獲取進(jìn)程名
     * @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中的點擊 事件跳轉(zhuǎn)到TestActivity扫沼,將會導(dǎo)致Application再次初始化

onCreate執(zhí)行多次

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

如何避免Application多次初始化

上面的代碼已經(jīng)給出了解決方法出爹,就是判斷當(dāng)前進(jìn)程是不是主進(jìn)程
若不是可以跳過主進(jìn)程的初始化
可以參考文章:https://blog.csdn.net/sz_chrome/article/details/72911392

多進(jìn)程的好處

常駐后臺任務(wù)應(yīng)用

核心后臺服務(wù)模塊和其他UI模塊進(jìn)行分離,保證應(yīng)用能更穩(wěn)定的提供服務(wù)
從而提升用戶體驗

解決OOM問題

吃內(nèi)存的大圖缎除,WebView等另開進(jìn)程严就,避免主進(jìn)程OOM

多模塊開發(fā)

諸如下載服務(wù),監(jiān)控服務(wù)等等另開進(jìn)程

多進(jìn)程帶來的問題

靜態(tài)變量和單例模式完全失效

因為進(jìn)程之間器罐,內(nèi)存是相互獨立的梢为,所以VM方法區(qū)的靜態(tài)變量
也都是獨立的,單例模式基于靜態(tài)變量轰坊,所以單例也會失效
在兩個不同進(jìn)程訪問一個相同類的靜態(tài)變量铸董,值未必相同

線程同步機(jī)制完全失效

Java的同步機(jī)制是VM來進(jìn)行調(diào)度的,兩個進(jìn)程擁有兩個不同的VM
所以肴沫,同步也會在多進(jìn)程環(huán)境下失效粟害,Synchronized,volatile關(guān)鍵字
等都是基于VM級別的同步颤芬,所以不要跨進(jìn)程去使用線程同步我磁,比如
主進(jìn)程有個生產(chǎn)者孽文,子進(jìn)程的消費者是無法正常使用消費功能的,
只能通過跨進(jìn)程通信夺艰,讓主進(jìn)程的消費者去消費,然后再回調(diào)

Application會多次創(chuàng)建

每個新進(jìn)程在創(chuàng)建的時候沉衣,都會新建一個Application郁副,所以多進(jìn)程還
會導(dǎo)致Application多次創(chuàng)建的問題,onCreate方法會多次調(diào)用豌习,一般
我們都會在onCreate里初始化操作存谎,那么會多次初始化,最好也不要在
Application中設(shè)置過多的靜態(tài)變量肥隆,導(dǎo)致內(nèi)存增加

文件讀寫并發(fā)訪問的問題

文件指的泛指所有需要并發(fā)訪問的文件既荚,例如:本地文件,數(shù)據(jù)庫文件栋艳,
sharepreference等恰聘。由于Java中,文件鎖吸占、隊列機(jī)制都是VM級別的晴叨,
所以不同進(jìn)程訪問同一個文件鎖是不管用的。(通過C++可以實現(xiàn)多進(jìn)程
文件鎖機(jī)制矾屯,不過不在文本討論范圍內(nèi)兼蕊。)所以在實際開發(fā)過程中,還是
避免多進(jìn)程同時訪問統(tǒng)一文件件蚕,多利用Android中IPC的C/S思想孙技,提供服務(wù),
接口調(diào)用排作,避免直接去訪問對方進(jìn)程的文件或者數(shù)據(jù)庫牵啦,提升設(shè)計美感,
同時也能提升代碼的穩(wěn)定性

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末纽绍,一起剝皮案震驚了整個濱河市蕾久,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拌夏,老刑警劉巖僧著,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異障簿,居然都是意外死亡盹愚,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門站故,熙熙樓的掌柜王于貴愁眉苦臉地迎上來皆怕,“玉大人毅舆,你說我怎么就攤上這事∮冢” “怎么了憋活?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長虱黄。 經(jīng)常有香客問我悦即,道長,這世上最難降的妖魔是什么橱乱? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任辜梳,我火速辦了婚禮,結(jié)果婚禮上泳叠,老公的妹妹穿的比我還像新娘作瞄。我一直安慰自己,他們只是感情好危纫,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布宗挥。 她就那樣靜靜地躺著,像睡著了一般叶摄。 火紅的嫁衣襯著肌膚如雪属韧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天蛤吓,我揣著相機(jī)與錄音宵喂,去河邊找鬼。 笑死会傲,一個胖子當(dāng)著我的面吹牛锅棕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播淌山,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼裸燎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了泼疑?” 一聲冷哼從身側(cè)響起德绿,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎退渗,沒想到半個月后移稳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡会油,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年个粱,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翻翩。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡都许,死狀恐怖稻薇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情胶征,我是刑警寧澤塞椎,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站睛低,受9級特大地震影響忱屑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜暇昂,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望伴嗡。 院中可真熱鬧急波,春花似錦、人聲如沸瘪校。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽阱扬。三九已至泣懊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間麻惶,已是汗流浹背馍刮。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留窃蹋,地道東北人卡啰。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像警没,于是被迫代替她去往敵國和親匈辱。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,167評論 25 707
  • 用兩張圖告訴你杀迹,為什么你的 App 會卡頓? - Android - 掘金 Cover 有什么料亡脸? 從這篇文章中你...
    hw1212閱讀 12,730評論 2 59
  • 面試必背 會舍棄、總結(jié)概括——根據(jù)我這些年面試和看面試題搜集過來的知識點匯總而來 建議根據(jù)我的寫的面試應(yīng)對思路中的...
    luoyangzk閱讀 6,756評論 6 173
  • 1 邂逅“貓掌柜” 秋日的午后树酪,陽光暖暖的浅碾。 在公司吃了午飯,小小習(xí)慣到樓下的“貓掌柜”坐一坐嗅回。找一個靠窗的角...
    簡_豆媽閱讀 886評論 4 2
  • 時光靜靜的想念及穗,我在頓河邊等待,也許是真的你不會來绵载,但是我會一直一直一個人默守埂陆,許多事情不要說苛白,一個眼神交流就夠了...
    不留心閱讀 509評論 2 6