Application

Application是什么

Application和Activity,Service一樣,是Android框架的一個(gè)系統(tǒng)組件,當(dāng)Android程序啟動(dòng)是系統(tǒng)會(huì)創(chuàng)建一個(gè)Application對(duì)象,用來(lái)存儲(chǔ)系統(tǒng)的一些信息。通常我們是不需要制定一個(gè)Application的,這時(shí)系統(tǒng)會(huì)自動(dòng)幫我們創(chuàng)建,如果需要?jiǎng)?chuàng)建自己的Application,創(chuàng)建一個(gè)類(lèi)繼承Application并在manifests的application標(biāo)簽中進(jìn)行注冊(cè)(只需要給application標(biāo)簽增加個(gè)name屬性吧自己的Application的名字寫(xiě)入)。Android系統(tǒng)會(huì)為每個(gè)程序運(yùn)行是創(chuàng)建一個(gè)Application的類(lèi)的對(duì)象且僅創(chuàng)建一個(gè),所以Application可以說(shuō)是單例(singleton)模式的一個(gè)類(lèi),且application對(duì)象的生命周期是整個(gè)程序中最長(zhǎng)的,生命周期就是這個(gè)程序的生命周期。因?yàn)樗侨值膯卫?,所以在不同的Activity,Service中獲得的對(duì)象都是同一個(gè)對(duì)象。所以通過(guò)Application來(lái)進(jìn)行一些數(shù)據(jù)傳遞,數(shù)據(jù)共享,數(shù)據(jù)緩存等操作。


Application生命周期

registerComponentCallbacks()&unregisterComponentCallbacks():

注冊(cè)和注銷(xiāo)ComponentCallbacks2回調(diào)接口,本質(zhì)上是復(fù)寫(xiě)ComponentCallbacks2回調(diào)接口里的方法從未實(shí)現(xiàn)更多的操作。

registerComponentCallbacke(new ComponentCallbacks2()){

@Override public void onTriMemory(int level){}

@Override public void onLowMemory(){}

@Override public void onConfigurationChanged(Configuration newConfig){}

}

registerActivityLifecycleCallbacks()&unregisterActivityLifecycleCallbacks():

注冊(cè)注銷(xiāo)對(duì)應(yīng)用程序內(nèi)所有Activity的生命周期監(jiān)聽(tīng)。當(dāng)應(yīng)用程序內(nèi)Activity生命周期發(fā)生變化時(shí)就會(huì)調(diào)用,實(shí)際上是調(diào)用registerActivityLifecycleCallbacks()里ActivityLifecycleCallbacks接口里的方法。

registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks(){

@Override public void onActivity Created(Activity activity, Bundle saveInstanceState){}

@Override public void onActivityStarted(Activity activity){

Log.d(TAG,"onActivityStarted: "+ activity.getLocalClassName());? ? ? ? ? ? }

@Override public void onActivityResumed(Activity activity){

Log.d(TAG,"onActivityResumed: "+ activity.getLocalClassName());? ? ? ? ? ? }

@Override public void onActivityPaused(Activity activity){

Log.d(TAG,"onActivityPaused: "+ activity.getLocalClassName());? ? ? ? ? ? }

@Override public void onActivityStopped(Activity activity){

Log.d(TAG,"onActivityStopped: "+ activity.getLocalClassName());? ? ? ? ? ? }

@Override public void onActivitySaveInstanceState(Activity activity, Bundle outState){? ? ? ? ? ? }

@Override public void onActivityDestroyed(Activity activity){

Log.d(TAG,"onActivityDestroyed: "+ activity.getLocalClassName());? ? ? ? ? ? }

})

public void onCreate();在應(yīng)用程序創(chuàng)建的時(shí)候調(diào)用,可以實(shí)現(xiàn)這個(gè)方法來(lái)創(chuàng)建和實(shí)例化任何應(yīng)用程序狀態(tài)變量或共享資源。還可以在這個(gè)方法里面得到Application的單例。不要進(jìn)行耗時(shí)操作,否則會(huì)拖慢應(yīng)用程序的啟動(dòng)速度。

public void onTerminate(); 當(dāng)終止應(yīng)用程序?qū)ο髸r(shí)調(diào)用,不保證一定被調(diào)用,當(dāng)程序時(shí)被內(nèi)核終止以便為其他應(yīng)用程序釋放資源,那么不會(huì)提醒,并且不調(diào)用應(yīng)用程序?qū)ο蟮膐nTerminate方法而直接終止進(jìn)程。

public void onLowMemory(); 當(dāng)系統(tǒng)資源匱乏的時(shí)候,我們可以在這里可以釋放額外的內(nèi)存,這個(gè)方法一般只會(huì)在后臺(tái)進(jìn)程已經(jīng)結(jié)束,但前臺(tái)應(yīng)用程序還是缺少內(nèi)存時(shí)調(diào)用??梢灾貙?xiě)這個(gè)方法來(lái)清空緩存或者不必要的資源。

public void onTrimMemory(int level);

OnTrimMemory()是 OnLowMemory() Android 4.0后的替代 API,OnLowMemory()= OnTrimMemory()中的TRIM_MEMORY_COMPLETE級(jí)別。當(dāng)運(yùn)行時(shí)決定當(dāng)前應(yīng)用程序應(yīng)該減少其內(nèi)存開(kāi)銷(xiāo)時(shí)(通常進(jìn)入后臺(tái)運(yùn)行時(shí)調(diào)用),包含一個(gè)level參數(shù),用于提供請(qǐng)求的上下文。

這里有傳入一個(gè)int類(lèi)型的參數(shù)level,它告訴APP們內(nèi)存不足的嚴(yán)重性(越高越嚴(yán)重)。假如這時(shí)候系統(tǒng)內(nèi)存不足,運(yùn)行著前臺(tái)和后臺(tái)一共幾個(gè)APP,這些不同的APP會(huì)收到系統(tǒng)不同的“勸告信息”:

TRIM_MEMORY_RUNNING_MODERATE:數(shù)值為5,系統(tǒng)內(nèi)存不足,前臺(tái)app釋放不用的內(nèi)存,內(nèi)存不夠殺掉其他應(yīng)用程序。

TRIM_MEMORY_RUNNING_LOW:數(shù)值10,系統(tǒng)內(nèi)存嚴(yán)重不足,前臺(tái)app釋放不用的內(nèi)存,內(nèi)存不夠殺掉其他多個(gè)應(yīng)用程序。

TRIM_MEMORY_RUNNING_CRITICAL:數(shù)值15,系統(tǒng)內(nèi)存嚴(yán)重不足可能都不足以支撐該前臺(tái)app的(執(zhí)行onLowMemory()方法)

TRIM_MEMORY_UI_HIDDEN:數(shù)值20,系統(tǒng)把APP從前臺(tái)切換到后臺(tái)?;厥誙I資源。

TRIM_MEMORY_BACKGROUND :數(shù)值40,內(nèi)存不足,殺掉后臺(tái)APP

TRIM_MEMORY_MODERATE :數(shù)值60,已進(jìn)入LRU緩存列表的中間位置,如果后面的APP進(jìn)程資源都被回收的話,下一個(gè)就是輪到它了

TRIM_MEMORY_COMPLETE :數(shù)值80已處于LRU緩存列表的后面位置,APP隨時(shí)都有被回收的風(fēng)險(xiǎn)

public void onConfigurationChanged(Configuration newConfig); 與Activity不同,配置改變時(shí),應(yīng)用程序不會(huì)終止和重啟。如果應(yīng)用程序使用的值依賴(lài)于特定的配置,則重寫(xiě)這個(gè)方法來(lái)加載這些值,或者在應(yīng)用程序級(jí)處理配置值的改變。


通過(guò)Application傳遞數(shù)據(jù)

假如有個(gè)Activity A,跳轉(zhuǎn)到Activity B,并需要推薦一些數(shù)據(jù),通常的作法是Intent.putExtra()讓Intent攜帶,或者有個(gè)Bundle把信息加入Bundle讓Intent推薦Bundle對(duì)象,實(shí)現(xiàn)傳遞。但這樣做有個(gè)問(wèn)題,Intent和Bundle所能攜帶的數(shù)據(jù)類(lèi)型都是一些基本數(shù)據(jù)類(lèi)型,如果類(lèi)型復(fù)雜的數(shù)據(jù)傳遞就比較麻煩了,通常需要實(shí)現(xiàn)Serializable或者Parcellable接口。這其實(shí)是Activit的一種IPC數(shù)據(jù)傳遞的方法。如果我們的兩個(gè)Acitivity在同一進(jìn)程中,只需要傳遞對(duì)象的引用就可以了。

在Application中創(chuàng)建一個(gè)HashMap,以字符串為索引,Object為value這樣我們的HashMap可以存儲(chǔ)任意類(lèi)型的對(duì)象了。在Activity A中把需要傳遞的對(duì)象放入這個(gè)HashMap,然后通過(guò)Intent或者其他途徑再把這所以的字符串傳遞給Activity B,ActivityB就可以根據(jù)這個(gè)字符串在HashMap中取出這個(gè)對(duì)象,只要再向下轉(zhuǎn)個(gè)型就實(shí)現(xiàn)了對(duì)象的傳遞。

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

在Application中建立兩個(gè)HashMap一個(gè)用于數(shù)據(jù)的傳遞一個(gè)用于緩存數(shù)據(jù)。比如有一個(gè)Activity需要從網(wǎng)站中獲取一些數(shù)據(jù),獲取完了之后我們就可以吧這個(gè)數(shù)據(jù)cache到Application中,當(dāng)頁(yè)面設(shè)置到其他Activity再回來(lái)的時(shí)候就可以直接實(shí)用緩存好的數(shù)據(jù)了。但如果需要cache一些大量的數(shù)據(jù),最好是cache一些(軟引用)SoftReference,并把這些數(shù)據(jù)cache到本地rom上或者sd卡上。如果在application中的緩存不存在,從本地緩存查找,如果本地?cái)?shù)據(jù)也不存在再?gòu)木W(wǎng)上獲取。使用application如果保存了一些不該保存的對(duì)象很容易導(dǎo)致內(nèi)存泄漏。如果在Application的onCreate中執(zhí)行比較耗時(shí)的操作,將直接影響啟動(dòng)的時(shí)間。一些清理工作不能依靠onTerminate完成,因?yàn)閍ndroid會(huì)盡量讓你的程序一直運(yùn)行,所以很有可能onTerminate不會(huì)調(diào)用。

在Java中內(nèi)存泄漏是指,某個(gè)或者某些對(duì)象已經(jīng)不再被使用應(yīng)該被gc回收,但有個(gè)對(duì)象一直持有這個(gè)對(duì)象的引用而阻止其被回收。比如說(shuō)TextView tv=new Textview(this);這里的this通常指的是Activity。所以這個(gè)TextView就持有這個(gè)引用。通常,當(dāng)我們轉(zhuǎn)動(dòng)手機(jī)的時(shí)候,Android會(huì)重新調(diào)用onCreate()方法生成一個(gè)新的Activity,原來(lái)的Activity就被gc回收。但如果有個(gè)對(duì)象比如一個(gè)view的作用域超過(guò)了這個(gè)Activity(比如有一個(gè)static對(duì)象或者我們把這個(gè)View的引用放到了Application中),這個(gè)時(shí)候原來(lái)的Activity不能被gc回收,Activity本身又持有很多對(duì)象的引用,所以整個(gè)Activity的內(nèi)存被泄漏了。

通常導(dǎo)致內(nèi)存泄漏核心原因

keeping a long-lived reference to a Context.持有一個(gè)Context的對(duì)象,從而gc不能回收。

情況如下:? ? ? ?

(1)一個(gè)View的作用域超出了所在的Activity的作用域(比如一個(gè)static的View或者把一個(gè)View cache到了application當(dāng)中etc。)注意靜態(tài)的數(shù)據(jù)和緩存中的數(shù)據(jù);以及數(shù)據(jù)釋放;

(2)某些與view關(guān)聯(lián)的Drawable的作用域超出了Activity的作用域。

(3)Runnable對(duì)象:比如在一個(gè)Activity中啟用了一個(gè)新線程去執(zhí)行一個(gè)任務(wù),在這期間這個(gè)Activity被系統(tǒng)回收了,但Runnable的任務(wù)還沒(méi)有執(zhí)行完畢并持有Activity的引用而泄漏,但這種泄漏一般一堆時(shí)間,只有Runable的線程執(zhí)行完畢,這個(gè)Activity又可以被正?;厥樟?。

(4)內(nèi)部類(lèi)的對(duì)象作用域超出了Activity的范圍:比如定義了一個(gè)內(nèi)部類(lèi)來(lái)存儲(chǔ)數(shù)據(jù),有把這個(gè)內(nèi)部類(lèi)的對(duì)象又傳給了其他Activity和Service等。因?yàn)閮?nèi)部類(lèi)的對(duì)象會(huì)持有這個(gè)類(lèi)的引用,所以也就持有了context的引用。解決方法是如果不需要當(dāng)前的引用把內(nèi)部類(lèi)寫(xiě)成static或者把內(nèi)部類(lèi)抽取出來(lái)變成一個(gè)單獨(dú)的類(lèi),或者把避免內(nèi)部對(duì)象作用域超出Activity的作用域。

Out Of Memery Error:在Android中每個(gè)程序所分到的內(nèi)存大小是有限的,如果超出這個(gè)數(shù)就誰(shuí)報(bào)Out Of Mermory Error。Android給程序分配的內(nèi)存大小與手機(jī)硬件有關(guān),以下是一些手機(jī)的數(shù)據(jù):G1:16M? Droid:24M Nexus One 32M? Xoom:48M。所以盡量把程序中的一些大的數(shù)據(jù)cache到本地文件,以免內(nèi)存泄漏。

記得數(shù)據(jù)傳遞完成之后,把存放在Application的HashMap中的數(shù)據(jù)remove掉,以免發(fā)生內(nèi)存泄漏。


Application被殺死的情況分析

為了決定在內(nèi)存較低的時(shí)候殺掉那個(gè)進(jìn)程,Android會(huì)根據(jù)運(yùn)行在這些進(jìn)程內(nèi)的組件以及他們的狀態(tài)把進(jìn)程劃分成一個(gè)“重要程度層次”,其重要程度按以下規(guī)則排序:

1:前端進(jìn)程可以是一個(gè)持有運(yùn)行在屏幕最前端并與用戶交互的Activity的進(jìn)程(onResume方法被調(diào)用時(shí)),也可以是持有一個(gè)正在運(yùn)行的IntertReceiver(也就是說(shuō)它正在執(zhí)行自己的onReceiverInrent方法)的進(jìn)程。在系統(tǒng)中,只會(huì)有少數(shù)這樣的進(jìn)程,并且除非內(nèi)存已經(jīng)低到不夠這些進(jìn)程運(yùn)行,否則系統(tǒng)不會(huì)主動(dòng)殺死這些進(jìn)程。這時(shí),設(shè)備通常已經(jīng)達(dá)到了需要內(nèi)存整理的狀態(tài),所以殺掉這些進(jìn)程時(shí)為了不讓用戶界面停止響應(yīng)。

2:可視進(jìn)程是持有一個(gè)被用戶可見(jiàn),但沒(méi)有顯示在最前端(onPause方法被調(diào)用時(shí))的Activity的進(jìn)程。舉例來(lái)說(shuō),這種進(jìn)程通常出現(xiàn)在一個(gè)前端Activity以一個(gè)對(duì)話框出現(xiàn)并保持前一個(gè)Activity可見(jiàn)時(shí),這種進(jìn)程被系統(tǒng)認(rèn)為是極其重要的,并且通常不會(huì)被殺掉,除非為了保持所有前端進(jìn)程正常運(yùn)行不得不殺死這些可見(jiàn)進(jìn)程。

3:服務(wù)進(jìn)程是持有一個(gè)Service的進(jìn)程,該Service是由startService()方法啟動(dòng)的,盡管這些進(jìn)程用戶不能直接看到,但它們做的工作用戶是十分關(guān)注的(例如,在后臺(tái)播放mp3或是在后臺(tái)下載上傳文件),所以,除非為了保持所有的前端進(jìn)程和可視進(jìn)程正常運(yùn)行外,系統(tǒng)是不會(huì)殺掉服務(wù)進(jìn)程的。

4:后臺(tái)進(jìn)程是持有一個(gè)不再被用戶可見(jiàn)的Activity(onStop()方法被調(diào)用時(shí))的進(jìn)程。這些進(jìn)程不會(huì)直接影響用戶體驗(yàn),加上這些進(jìn)程已經(jīng)完整的,正確的完成了自己的生命周期(訪問(wèn)Activity查看跟多細(xì)節(jié)),系統(tǒng)會(huì)在為前三種進(jìn)程釋放內(nèi)存時(shí)隨時(shí)殺掉這些后臺(tái)進(jìn)程。通常會(huì)有很多的后臺(tái)進(jìn)程在運(yùn)行,所以這些進(jìn)程被存放在一個(gè)LRU列表中,以保證在低內(nèi)存的時(shí)候,最近一個(gè)被用戶看到的進(jìn)程最后被殺掉。

5:空進(jìn)程時(shí)沒(méi)有持有任何活動(dòng)應(yīng)用組件的進(jìn)程,保留這種進(jìn)程的唯一理由時(shí)為了提供一種緩存機(jī)制,縮短他的應(yīng)用下次運(yùn)行時(shí)的啟動(dòng)時(shí)間,就本身而言,系統(tǒng)殺掉這些進(jìn)程的目的時(shí)為了在這些空進(jìn)程和底層的核心緩存之間平衡整個(gè)系統(tǒng)的資源。

當(dāng)需要給一個(gè)進(jìn)程分類(lèi)的時(shí)候,系統(tǒng)會(huì)在該進(jìn)程中處于活動(dòng)狀態(tài)的所有組件里掉選一個(gè)重要等級(jí)最高作為分類(lèi)依據(jù)。查看Activity,Service,IntentReceiver的文檔,了解每個(gè)組件在進(jìn)程整個(gè)生命周期中的貢獻(xiàn)。每一個(gè)classes 的文檔詳細(xì)描述它們?cè)诟髯詰?yīng)用的生命周期中所起的作用。

Application的context

1,他描述的時(shí)一個(gè)應(yīng)用程序環(huán)境的信息,即上下文

2,該類(lèi)是一個(gè)抽象(abstract class)類(lèi),Android提供了該抽象類(lèi)的具體實(shí)現(xiàn)類(lèi)(ContextIml)

3,通過(guò)它我們可以獲取應(yīng)用程序的資源和類(lèi),也包括一些應(yīng)用級(jí)別操作,例如:?jiǎn)?dòng)一個(gè)Activity,發(fā)送廣播,接受Intent信息等

getContext()、getApplication()、getApplicationContext、getActivity()的區(qū)別:

(1) getContext()? ? ? 獲取到當(dāng)前對(duì)象的上下文

(2)getApplication()? 獲取Application的對(duì)象

(3)getApplicationContext()? 獲取到當(dāng)前應(yīng)用程序的上下文。生命周期隨著應(yīng)用程序的銷(xiāo)毀而銷(xiāo)毀,每個(gè)Activity都有自己的上下文,而整個(gè)應(yīng)用只有一個(gè)上下文。

(4)getActivity()? ? ? ? 獲取Acitivty對(duì)象

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容