Android Application的生命周期

導(dǎo)讀

Application是什么

Application和Activity、Service一樣是Android框架的一個系統(tǒng)組件,當(dāng)Android程序啟動時系統(tǒng)會創(chuàng)建一個 Application對象,用來存儲系統(tǒng)的一些信息。
Application的生命周期等于這個程序的生命周期,又因?yàn)锳pplication是全局的單例的,所以在不同的Activity,Service中獲得的對象都是同一個對象。所以通過Application來進(jìn)行一些數(shù)據(jù)傳遞、數(shù)據(jù)共享、數(shù)據(jù)緩存等操作。

一般寫Demo是不需要指定一個Application的,這時系統(tǒng)會自動幫我們創(chuàng)建;而實(shí)際項(xiàng)目中基本上都是需要創(chuàng)建自己的Application的,創(chuàng)建一個類繼承 Application并在AndroidManifest清單文件中的Application標(biāo)簽中進(jìn)行注冊(只需要給Application標(biāo)簽增加個name屬性把自己的 Application的名字定入即可)。android系統(tǒng)會為每個程序運(yùn)行時創(chuàng)建一個Application類的對象且僅創(chuàng)建一個,所以Application可以說是單例 (singleton)模式的一個類。

Application生命周期

  1. onConfigurationChanged( ) :在配置被改變時觸發(fā) 。
  2. onCreate() :在程序創(chuàng)建時創(chuàng)建。
  3. onLowMemory() :內(nèi)存不夠時觸發(fā)。
  4. onTerminate() :當(dāng)終止程序時調(diào)用 但是不能保證一定調(diào)用
  5. onTrimMemory() :在內(nèi)存清理時觸發(fā)
public class App extends Application {
    @Override
    public void onCreate() {
        // 程序創(chuàng)建的時候執(zhí)行
        Log.d(TAG, "onCreate");
        super.onCreate();
    }
    @Override
    public void onTerminate() {
        // 程序終止的時候執(zhí)行
        Log.d(TAG, "onTerminate");
        super.onTerminate();
    }
    @Override
    public void onLowMemory() {
        // 低內(nèi)存的時候執(zhí)行
        Log.d(TAG, "onLowMemory");
        super.onLowMemory();
    }
    @Override
    public void onTrimMemory(int level) {
        // 程序在內(nèi)存清理的時候執(zhí)行
        Log.d(TAG, "onTrimMemory");
        super.onTrimMemory(level);
    }
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        Log.d(TAG, "onConfigurationChanged");
        super.onConfigurationChanged(newConfig);
    }
}

使用Application傳遞數(shù)據(jù)

在android中通常會使用Intent(Bundle)進(jìn)行數(shù)據(jù)通信,但一般為簡單數(shù)據(jù)類型,如數(shù)據(jù)類型相對復(fù)雜(如對象)則需要實(shí)現(xiàn) Serializable或者Parcelable接口,其實(shí)可以使用Application傳遞復(fù)雜數(shù)據(jù)。

基本思路是這樣的。在Application中創(chuàng)建一個HashMap ,以字符串為key,Object為value這樣我們的HashMap就可以存儲任何類型的對象了

使用Application數(shù)據(jù)緩存

既然可以在Application中使用HashMap 進(jìn)行傳遞數(shù)據(jù),自然是可以進(jìn)行一些緩存動作了,不過筆者基本沒有這樣操作過,同時需要注意內(nèi)存泄漏。

Application的Context

  • Context是一個應(yīng)用程序環(huán)境的信息,即上下文。
  • 該類是一個抽象(abstract class)類,Android提供了該抽象類的具體實(shí)現(xiàn)類(后面我們會講到是ContextIml類)。
  • 通過它我們可以獲取應(yīng)用程序的資源和類,也包括一些應(yīng)用級別操作,例如:啟動一個Activity,發(fā)送廣播,接受Intent信息 等


    Context

可以看到Activity、Service、Application都是Context的子類。
也就是說,Android系統(tǒng)的角度來理解:Context是一個場景,代表與操作系統(tǒng)的交互的一種過程。從程序的角度上來理解:Context是個抽象類,而Activity、Service、Application等都是該類的一個實(shí)現(xiàn)。

Application的oncreate方法會執(zhí)行幾次,會不會多次執(zhí)行?

通常情況下,App默認(rèn)開啟一個進(jìn)程,進(jìn)程名就是AndroidManifest.xml文件中我們項(xiàng)目的包名,所有的基本組件都是在這個進(jìn)程中進(jìn)行,Application的onCreate方法會被執(zhí)行一次。但是如果我們工程涉及到多進(jìn)程,那么就會出現(xiàn)Application的onCreate方法被多次執(zhí)行情況。

解決oncreate方法多次被調(diào)用:

1、定義獲取進(jìn)程的方法

    private String getProcessName(Context context) {
        try {
            ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
            List<ActivityManager.RunningAppProcessInfo> runningApps = am.getRunningAppProcesses();
            if (runningApps == null) {
                return null;
            }
            for (ActivityManager.RunningAppProcessInfo proInfo : runningApps) {
                if (proInfo.pid == android.os.Process.myPid()) {
                    if (proInfo.processName != null) {
                        return proInfo.processName;
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

2、在onCreate方法中進(jìn)行比對

 @Override
    public void onCreate() {
        super.onCreate();
        String processName = getProcessName(this);
        if (processName!= null) {
            String pkName = this.getPackageName();
            //只有主進(jìn)程,才執(zhí)行后續(xù)邏輯
            if(processName.equals(pkName)==false) {
                return;
            }
        }

使用Application避免一些內(nèi)存泄漏(Memory Leak)

在Java中內(nèi)存泄漏是指某個(某些)對象已經(jīng)不在被使用應(yīng)該被GC回收,但有一個對象持有這個對象的引用而阻止這個對象被回收。

比如在項(xiàng)目中經(jīng)常用到單例模式,而很多單例是需要傳遞Context的,由于sInstance是一個static且強(qiáng)引用的,若此時傳遞Context的是xxxActivity.this,那么這個xxxActivity就不會被內(nèi)存回收,就會造成內(nèi)存泄漏。

解決辦法就是Context傳遞context.getApplicationContext()

ps 經(jīng)常導(dǎo)致內(nèi)存泄漏核心原因分析(跳轉(zhuǎn)連接)

以下內(nèi)容等待被編輯到指定位置
ps 經(jīng)常導(dǎo)致內(nèi)存泄漏核心原因分析(跳轉(zhuǎn)連接)

keeping a long-lived reference to a Context

上述是常見的內(nèi)存泄漏的提示,即持有一個context的對象,從而GC不能回收,為什么會有這樣的情況呢

  • 一個View的作用域超出了所在的Activity的作用域,比如一個static的View或者把一個View cache到了application
  • 某些與View關(guān)聯(lián)的Drawable的作用域超出了Activity的作用域.
  • Runnable對象:比如在一個Activity中啟用了一個新線程去執(zhí)行一個任務(wù),在這期間這個Activity被系統(tǒng)回收了, 但Runnalbe的 任務(wù)還沒有執(zhí)行完畢并持有Activity的引用而泄漏,但這種泄漏一般來泄漏一段時間,只有Runnalbe的線程執(zhí)行完閉,這個 Activity又可以被正?;厥樟?。
  • 內(nèi)存類的對象作用域超出Activity的范圍:比如定義了一個內(nèi)存類來存儲數(shù)據(jù),又把這個內(nèi)存類的對象傳給了其它Activity、Service等。因?yàn)閮?nèi)部類的對象會持有當(dāng)前類的引用,所以也就持有了Context的引用。
    解決方法是如果不需要當(dāng)前的引用把內(nèi)部類寫成static或者把內(nèi)部類抽取出來變成一個單獨(dú)的類,或者作用域超出Activity的作用域。
    Out Of Memery Error 在Android中每一個程序所分到的內(nèi)存大小是有限的,如果超過了這個數(shù)就會報(bào)Out Of Memory Error。 Android給程序分配的內(nèi)存大小與手機(jī)硬件有關(guān),以下是一些手機(jī)的數(shù)據(jù):
    G1:16M Droid:24 Nexus One:32M Xoom:48Ms
    所以盡量把程序中的一些大的數(shù)據(jù)cache到本地文件。以免內(nèi)存使用量超標(biāo)。
    記得數(shù)據(jù)傳遞完成之后,把存放在application的HashMap中的數(shù)據(jù)remove掉,以免發(fā)生內(nèi)存的泄漏。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,836評論 6 540
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,275評論 3 428
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,904評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,633評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,368評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,736評論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,740評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,919評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,481評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,235評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,427評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,968評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,656評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,055評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,348評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,160評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,380評論 2 379

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