Application

Application是什么

Application和Activity哼蛆,Service一樣,是Android框架的一個系統(tǒng)組件骚勘,當(dāng)Android程序啟動是系統(tǒng)會創(chuàng)建一個Application對象猾编,用來存儲系統(tǒng)的一些信息桥爽。通常我們是不需要制定一個Application的纳击,這時系統(tǒng)會自動幫我們創(chuàng)建休建,如果需要創(chuàng)建自己的Application,創(chuàng)建一個類繼承Application并在manifests的application標(biāo)簽中進(jìn)行注冊(只需要給application標(biāo)簽增加個name屬性吧自己的Application的名字寫入)评疗。Android系統(tǒng)會為每個程序運行是創(chuàng)建一個Application的類的對象且僅創(chuàng)建一個,所以Application可以說是單例(singleton)模式的一個類茵烈,且application對象的生命周期是整個程序中最長的百匆,生命周期就是這個程序的生命周期。因為他是全局的單例的呜投,所以在不同的Activity加匈,Service中獲得的對象都是同一個對象。所以通過Application來進(jìn)行一些數(shù)據(jù)傳遞仑荐,數(shù)據(jù)共享雕拼,數(shù)據(jù)緩存等操作。


Application生命周期

registerComponentCallbacks()&unregisterComponentCallbacks():

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

registerComponentCallbacke(new ComponentCallbacks2()){

@Override public void onTriMemory(int level){}

@Override public void onLowMemory(){}

@Override public void onConfigurationChanged(Configuration newConfig){}

}

registerActivityLifecycleCallbacks()&unregisterActivityLifecycleCallbacks():

注冊注銷對應(yīng)用程序內(nèi)所有Activity的生命周期監(jiān)聽。當(dāng)應(yīng)用程序內(nèi)Activity生命周期發(fā)生變化時就會調(diào)用,實際上是調(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)建的時候調(diào)用衰絮,可以實現(xiàn)這個方法來創(chuàng)建和實例化任何應(yīng)用程序狀態(tài)變量或共享資源。還可以在這個方法里面得到Application的單例磷醋。不要進(jìn)行耗時操作猫牡,否則會拖慢應(yīng)用程序的啟動速度。

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

public void onLowMemory(); 當(dāng)系統(tǒng)資源匱乏的時候,我們可以在這里可以釋放額外的內(nèi)存缩歪,這個方法一般只會在后臺進(jìn)程已經(jīng)結(jié)束归薛,但前臺應(yīng)用程序還是缺少內(nèi)存時調(diào)用》蓑可以重寫這個方法來清空緩存或者不必要的資源主籍。

public void onTrimMemory(int level);

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

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

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

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

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

TRIM_MEMORY_UI_HIDDEN:數(shù)值20戏羽,系統(tǒng)把APP從前臺切換到后臺÷コ裕回收UI資源始花。

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

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

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

public void onConfigurationChanged(Configuration newConfig); 與Activity不同砌函,配置改變時,應(yīng)用程序不會終止和重啟溜族。如果應(yīng)用程序使用的值依賴于特定的配置讹俊,則重寫這個方法來加載這些值,或者在應(yīng)用程序級處理配置值的改變煌抒。


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

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

在Application中創(chuàng)建一個HashMap癞尚,以字符串為索引,Object為value這樣我們的HashMap可以存儲任意類型的對象了乱陡。在Activity A中把需要傳遞的對象放入這個HashMap浇揩,然后通過Intent或者其他途徑再把這所以的字符串傳遞給Activity B,ActivityB就可以根據(jù)這個字符串在HashMap中取出這個對象憨颠,只要再向下轉(zhuǎn)個型就實現(xiàn)了對象的傳遞临燃。

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

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

在Java中內(nèi)存泄漏是指鳍悠,某個或者某些對象已經(jīng)不再被使用應(yīng)該被gc回收税娜,但有個對象一直持有這個對象的引用而阻止其被回收。比如說TextView tv=new Textview(this)藏研;這里的this通常指的是Activity敬矩。所以這個TextView就持有這個引用。通常蠢挡,當(dāng)我們轉(zhuǎn)動手機(jī)的時候弧岳,Android會重新調(diào)用onCreate()方法生成一個新的Activity,原來的Activity就被gc回收业踏。但如果有個對象比如一個view的作用域超過了這個Activity(比如有一個static對象或者我們把這個View的引用放到了Application中)禽炬,這個時候原來的Activity不能被gc回收,Activity本身又持有很多對象的引用堡称,所以整個Activity的內(nèi)存被泄漏了瞎抛。

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

keeping a long-lived reference to a Context.持有一個Context的對象,從而gc不能回收却紧。

情況如下:? ? ? ?

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

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

(3)Runnable對象:比如在一個Activity中啟用了一個新線程去執(zhí)行一個任務(wù),在這期間這個Activity被系統(tǒng)回收了巫俺,但Runnable的任務(wù)還沒有執(zhí)行完畢并持有Activity的引用而泄漏认烁,但這種泄漏一般一堆時間,只有Runable的線程執(zhí)行完畢介汹,這個Activity又可以被正橙次耍回收了。

(4)內(nèi)部類的對象作用域超出了Activity的范圍:比如定義了一個內(nèi)部類來存儲數(shù)據(jù)嘹承,有把這個內(nèi)部類的對象又傳給了其他Activity和Service等窗价。因為內(nèi)部類的對象會持有這個類的引用,所以也就持有了context的引用叹卷。解決方法是如果不需要當(dāng)前的引用把內(nèi)部類寫成static或者把內(nèi)部類抽取出來變成一個單獨的類撼港,或者把避免內(nèi)部對象作用域超出Activity的作用域坪它。

Out Of Memery Error:在Android中每個程序所分到的內(nèi)存大小是有限的,如果超出這個數(shù)就誰報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)存較低的時候殺掉那個進(jìn)程,Android會根據(jù)運行在這些進(jìn)程內(nèi)的組件以及他們的狀態(tài)把進(jìn)程劃分成一個“重要程度層次”扣汪,其重要程度按以下規(guī)則排序:

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

2:可視進(jìn)程是持有一個被用戶可見响牛,但沒有顯示在最前端(onPause方法被調(diào)用時)的Activity的進(jìn)程。舉例來說赫段,這種進(jìn)程通常出現(xiàn)在一個前端Activity以一個對話框出現(xiàn)并保持前一個Activity可見時呀打,這種進(jìn)程被系統(tǒng)認(rèn)為是極其重要的,并且通常不會被殺掉糯笙,除非為了保持所有前端進(jìn)程正常運行不得不殺死這些可見進(jìn)程贬丛。

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

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

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

當(dāng)需要給一個進(jìn)程分類的時候桦锄,系統(tǒng)會在該進(jìn)程中處于活動狀態(tài)的所有組件里掉選一個重要等級最高作為分類依據(jù)扎附。查看Activity,Service结耀,IntentReceiver的文檔留夜,了解每個組件在進(jìn)程整個生命周期中的貢獻(xiàn)。每一個classes 的文檔詳細(xì)描述它們在各自應(yīng)用的生命周期中所起的作用图甜。

Application的context

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

2黑毅,該類是一個抽象(abstract class)類嚼摩,Android提供了該抽象類的具體實現(xiàn)類(ContextIml)

3,通過它我們可以獲取應(yīng)用程序的資源和類矿瘦,也包括一些應(yīng)用級別操作枕面,例如:啟動一個Activity,發(fā)送廣播匪凡,接受Intent信息等

getContext()膊畴、getApplication()、getApplicationContext病游、getActivity()的區(qū)別:

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

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

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市滋尉,隨后出現(xiàn)的幾起案子玉控,更是在濱河造成了極大的恐慌,老刑警劉巖狮惜,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件高诺,死亡現(xiàn)場離奇詭異碌识,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)虱而,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進(jìn)店門筏餐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人牡拇,你說我怎么就攤上這事魁瞪。” “怎么了惠呼?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵导俘,是天一觀的道長。 經(jīng)常有香客問我剔蹋,道長旅薄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任滩租,我火速辦了婚禮赋秀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘律想。我一直安慰自己猎莲,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布技即。 她就那樣靜靜地躺著著洼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪而叼。 梳的紋絲不亂的頭發(fā)上身笤,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天,我揣著相機(jī)與錄音葵陵,去河邊找鬼液荸。 笑死,一個胖子當(dāng)著我的面吹牛脱篙,可吹牛的內(nèi)容都是我干的娇钱。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼绊困,長吁一口氣:“原來是場噩夢啊……” “哼文搂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起秤朗,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤煤蹭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體硝皂,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡常挚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了稽物。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片待侵。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖姨裸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情怨酝,我是刑警寧澤傀缩,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站农猬,受9級特大地震影響赡艰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜斤葱,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一慷垮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧揍堕,春花似錦料身、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至楞慈,卻和暖如春幔烛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背囊蓝。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工饿悬, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人聚霜。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓狡恬,卻偏偏與公主長得像,于是被迫代替她去往敵國和親俯萎。 傳聞我的和親對象是個殘疾皇子傲宜,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,870評論 2 361

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