Activity與Fragment生命周期探討

一.Activity生命周期探討

圖1.Activity生命周期

其實(shí)這張圖已經(jīng)說(shuō)明了activity的生命周期漱病,但是在這里需要的注意的是焙糟,
(1)onCreat是activity正在被創(chuàng)建冕茅,也就是說(shuō)此時(shí)的UI操作不會(huì)更新UI落午,比如setText操作析显,所以此時(shí)在子線程調(diào)用setText不會(huì)報(bào)線程錯(cuò)誤鲫咽。詳解可見(jiàn)Android子線程更新View的探索,在這個(gè)方法內(nèi)我們可以做一些初始化工作。

(2)onRestart需要注意的是:activity正在重新啟動(dòng)谷异,一般情況下分尸,activity從不可見(jiàn)狀態(tài)到可見(jiàn)狀態(tài),onRestart才會(huì)被調(diào)用歹嘹,但是一定要注意的是一般來(lái)說(shuō)這是用戶行為導(dǎo)致activity不可見(jiàn)的時(shí)候箩绍,此時(shí)變?yōu)榭梢?jiàn)的時(shí)候才會(huì)調(diào)用onRestart,這里所說(shuō)的用戶行為就是用戶按home鍵尺上,或者進(jìn)入“新”的activity伶选。這樣的操作會(huì)使activity先執(zhí)行onPause,后執(zhí)行onStop,這樣回到這個(gè)activity會(huì)調(diào)用onRestart尖昏。為什么我這里強(qiáng)調(diào)說(shuō)用戶行為導(dǎo)致的不可見(jiàn)狀態(tài)仰税,等下我會(huì)說(shuō)。抽诉。陨簇。。

(3)onStart的時(shí)候迹淌,activity可見(jiàn)河绽,但是沒(méi)有出現(xiàn)在前臺(tái),無(wú)法與用戶交互

(4)onResume的時(shí)候唉窃,activity已經(jīng)可見(jiàn)耙饰,并且出現(xiàn)在前臺(tái)開(kāi)始活動(dòng),與onStart相比纹份,activity都已經(jīng)可見(jiàn)苟跪,但是onStart的時(shí)候activity還在后臺(tái),onResume才顯示在前臺(tái)

(5)onPause主要注意的是:此時(shí)的activity正在被停止蔓涧,接下來(lái)馬上調(diào)用onStop件已。特殊情況下快速回到該activity,onStop不會(huì)執(zhí)行元暴,會(huì)去執(zhí)行onResume篷扩。
一般在這個(gè)生命周期內(nèi)做存儲(chǔ)數(shù)據(jù)、停止動(dòng)畫(huà)工作茉盏,但不能太耗時(shí)鉴未。
為什么特殊強(qiáng)調(diào)呢枢冤,因?yàn)樵揳ctivity的onPause執(zhí)行完了,才回去執(zhí)行新的activity的onResume铜秆,一旦耗時(shí)掏导,必然會(huì)拖慢新的activity的顯示。

(6)onStop:此時(shí)的activity即將停止羽峰。在這里可以做稍微重量級(jí)的操作,同樣也不能耗時(shí)添瓷。

(7)onDestroy:此時(shí)的activity即將被回收梅屉,在這里會(huì)做一些回收工作和最終資源釋放。

在這里著重講解一下onStart與onRusume鳞贷,onPause與onStop區(qū)別
onStart與onRusume兩種狀態(tài)雖都可見(jiàn)坯汤,但onStart時(shí)還無(wú)法與用戶交互,并未獲得焦點(diǎn)搀愧。onRusume時(shí)頁(yè)面已獲得焦點(diǎn)惰聂,可與用戶交互;onPause時(shí)頁(yè)面還在前臺(tái)咱筛,只不過(guò)頁(yè)面已失去焦點(diǎn)搓幌,無(wú)法與用戶交互了,onStop時(shí)已不可見(jiàn)了迅箩。

activity四個(gè)狀態(tài)所在的生命周期:

  • Running狀態(tài):一個(gè)新的Activity啟動(dòng)入棧后溉愁,它在屏幕最前端,處于棧的最頂端饲趋,此時(shí)它處于可見(jiàn)并可和用戶交互的激活狀態(tài)拐揭。
  • Paused狀態(tài):依舊在用戶可見(jiàn)狀態(tài),但是界面焦點(diǎn)已經(jīng)失去奕塑,此Activity無(wú)法與用戶進(jìn)行交互堂污。當(dāng)Activity被另一個(gè)透明或者Dialog樣式的Activity覆蓋時(shí)的狀態(tài)。此時(shí)它依然與窗口管理器保持連接龄砰,系統(tǒng)繼續(xù)維護(hù)其內(nèi)部狀態(tài)盟猖,它仍然可見(jiàn),但它已經(jīng)失去了焦點(diǎn)换棚,故不可與用戶交互扒披。所以就解釋為什么啟動(dòng)一個(gè)dialogActivity或者透明Activity時(shí),原Activity只執(zhí)行了onPause生命周期圃泡,并未執(zhí)行onStop
  • Stopped狀態(tài):用戶看不到當(dāng)前界面,也無(wú)法與用戶進(jìn)行交互 完全被覆蓋碟案。當(dāng)Activity不可見(jiàn)時(shí),Activity處于Stopped狀態(tài)颇蜡。當(dāng)Activity處于此狀態(tài)時(shí)价说,一定要保存當(dāng)前數(shù)據(jù)和當(dāng)前的UI狀態(tài)辆亏,否則一旦Activity退出或關(guān)閉時(shí),當(dāng)前的數(shù)據(jù)和UI狀態(tài)就丟失了鳖目。
  • Killed狀態(tài):Activity被殺掉以后或者被啟動(dòng)以前扮叨,處于Killed狀態(tài)。這是Activity已從Activity堆棧中移除领迈,需要重新啟動(dòng)才可以顯示和使用彻磁。

4種狀態(tài)中,Running狀態(tài)和Paused狀態(tài)是可見(jiàn)的狸捅,Stopped狀態(tài)和Killed狀態(tài)時(shí)不可見(jiàn)的衷蜓。


Activity注意事項(xiàng)

Activity中所有和狀態(tài)相關(guān)的回調(diào)函數(shù):


在這里我會(huì)特別提出一個(gè)point,就是異常情況下activity被殺死尘喝,而后被重新創(chuàng)建的情況磁浇。


異常情況下activity的重建過(guò)程

這張圖非常重要,可以幫我們解決異常情況下activity如何正承嗤剩回復(fù)的問(wèn)題
當(dāng)系統(tǒng)停止activity時(shí)置吓,它會(huì)調(diào)用onSaveInstanceState()(過(guò)程1),如果activity被銷(xiāo)毀了缔赠,但是需要?jiǎng)?chuàng)建同樣的實(shí)例衍锚,系統(tǒng)會(huì)把過(guò)程1中的狀態(tài)數(shù)據(jù)傳給onCreate()和onRestoreInstanceState(),所以我們要在onSaveInstanceState()內(nèi)做保存參數(shù)的動(dòng)作嗤堰,在onRestoreInstanceState()做獲取參數(shù)的動(dòng)作构拳。

Save Activity State

static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
    
    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

獲取參數(shù)操作:

onCreate() 方法

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // Always call the superclass first
   
    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
        // Restore value of members from saved state
        mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
        mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
    } else {
        // Probably initialize members with default values for a new instance
    }
    ...
}

也可以

onRestoreInstanceState()方法

public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);
   
    // Restore state members from saved instance
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

頁(yè)面切換

AB頁(yè)面切換

橫豎屏切換時(shí) Activity 的生命周期
1、不設(shè)置 Activity 的 android:configChanges 時(shí)梁棠,切屏?xí)匦抡{(diào)用各個(gè)生命周期 默認(rèn)首先銷(xiāo)毀當(dāng)前 activity置森,然后重新加載。如下圖符糊,當(dāng)橫豎屏切換時(shí)先執(zhí)行 onPause/onStop 方法


2凫海、設(shè)置 Activity 的 android:configChanges="orientation|keyboardHidden|screenSize"時(shí),切屏不會(huì)重新調(diào) 用各個(gè)生命周期男娄,只會(huì)執(zhí)行 onConfigurationChanged 方法行贪。

二.Fragment生命周期探討

圖2.Fragment生命周期

這張圖很好的說(shuō)明了Fragment與Actvivity生命周期的整合情況。通過(guò)對(duì)Fragment和Activity對(duì)比模闲,將會(huì)發(fā)現(xiàn)許多不同之處建瘫,主要原因是因?yàn)锳ctivity和Fragment之間需要交互。
在這里我首先需要提出的一些points:

  • Fragment是直接從Object繼承的尸折,而Activity是Context的子類(lèi)啰脚。因此我們可以得出結(jié)論:Fragment不是Activity的擴(kuò)展。但是與Activity一樣实夹,在我們使用Fragment的時(shí)候我們總會(huì)擴(kuò)展Fragment(或者是她的子類(lèi))橄浓,并可以通過(guò)子類(lèi)更改她的行為粒梦。
  • 使用Fragment時(shí),必要構(gòu)建一個(gè)無(wú)參構(gòu)造函數(shù)荸实,系統(tǒng)會(huì)默認(rèn)帶匀们。但一但寫(xiě)有參構(gòu)造函數(shù),就必要構(gòu)建無(wú)參構(gòu)造函數(shù)准给。一般來(lái)說(shuō)我們傳參數(shù)給Fragment泄朴,會(huì)通過(guò)bundle,而不會(huì)用構(gòu)造方法傳露氮,代碼如下:
public static MyFragment newInstance(int index){  
    MyFragment mf = new MyFragment();  
    Bundle args = new Bundle();  
    args.putInt("index",index);  
    mf.setArguments(args);  
    return mf;  
} 

下面來(lái)分析生命周期祖灰,然后根據(jù)這些我會(huì)強(qiáng)調(diào)一些point。
(1)onAttach:onAttach()回調(diào)將在Fragment與其Activity關(guān)聯(lián)之后調(diào)用沦辙。需要使用Activity的引用或者使用Activity作為其他操作的上下文,將在此回調(diào)方法中實(shí)現(xiàn)讹剔。
需要注意的是:將Fragment附加到Activity以后油讯,就無(wú)法再次調(diào)用setArguments()——除了在最開(kāi)始,無(wú)法向初始化參數(shù)添加內(nèi)容延欠。

(2)onCreate(Bundle savedInstanceState):此時(shí)的Fragment的onCreat回調(diào)時(shí)陌兑,該fragmet還沒(méi)有獲得Activity的onCreate()已完成的通知,所以不能將依賴于Activity視圖層次結(jié)構(gòu)存在性的代碼放入此回調(diào)方法中由捎。在onCreate()回調(diào)方法中兔综,我們應(yīng)該盡量避免耗時(shí)操作。此時(shí)的bundle就可以獲取到activity傳來(lái)的參數(shù)

@Override public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
  
        Bundle args = getArguments();  
        if (args != null) {  
            mLabel = args.getCharSequence("label", mLabel);  
        }  
    }  

(3)onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState): 其中的Bundle為狀態(tài)包與上面的bundle不一樣狞玛。
注意的是:不要將視圖層次結(jié)構(gòu)附加到傳入的ViewGroup父元素中软驰,該關(guān)聯(lián)會(huì)自動(dòng)完成。如果在此回調(diào)中將碎片的視圖層次結(jié)構(gòu)附加到父元素心肪,很可能會(huì)出現(xiàn)異常锭亏。
這句話什么意思呢?就是不要把初始化的view視圖主動(dòng)添加到container里面硬鞍,以為這會(huì)系統(tǒng)自帶慧瘤,所以inflate函數(shù)的第三個(gè)參數(shù)必須填false,而且不能出現(xiàn)container.addView(v)的操作固该。

View v = inflater.inflate(R.layout.hello_world, container, false);

(4)onActivityCreated:onActivityCreated()回調(diào)會(huì)在Activity完成其onCreate()回調(diào)之后調(diào)用锅减。在調(diào)用onActivityCreated()之前,Activity的視圖層次結(jié)構(gòu)已經(jīng)準(zhǔn)備好了伐坏,這是在用戶看到用戶界面之前你可對(duì)用戶界面執(zhí)行的最后調(diào)整的地方怔匣。
強(qiáng)調(diào)的point:如果Activity和她的Fragment是從保存的狀態(tài)重新創(chuàng)建的,此回調(diào)尤其重要桦沉,也可以在這里確保此Activity的其他所有Fragment已經(jīng)附加到該Activity中了

(5)Fragment與Activity相同生命周期調(diào)用:接下來(lái)的onStart()\onResume()\onPause()\onStop()回調(diào)方法將和Activity的回調(diào)方法進(jìn)行綁定劫狠,也就是說(shuō)與Activity中對(duì)應(yīng)的生命周期相同拴疤,因此不做過(guò)多介紹。

(6)onDestroyView:該回調(diào)方法在視圖層次結(jié)構(gòu)與Fragment分離之后調(diào)用独泞。

(7)onDestroy:不再使用Fragment時(shí)調(diào)用呐矾。(備注:Fragment仍然附加到Activity并任然可以找到,但是不能執(zhí)行其他操作)

(8)onDetach:Fragme生命周期最后回調(diào)函數(shù)懦砂,調(diào)用后蜒犯,F(xiàn)ragment不再與Activity綁定,釋放資源荞膘。

Fragment注意事項(xiàng)

在使用Fragment時(shí)衔沼,我發(fā)現(xiàn)了一個(gè)金礦,那就是setRetainInstance()方法,此方法可以有效地提高系統(tǒng)的運(yùn)行效率椰于,對(duì)流暢性要求較高的應(yīng)用可以適當(dāng)采用此方法進(jìn)行設(shè)置梭姓。


setRetainInstance(true)使用效果

Fragment有一個(gè)非常強(qiáng)大的功能——就是可以在Activity重新創(chuàng)建時(shí)可以不完全銷(xiāo)毀Fragment,以便Fragment可以恢復(fù)屠升。在onCreate()方法中調(diào)用setRetainInstance(true/false)方法是最佳位置潮改。當(dāng)Fragment恢復(fù)時(shí)的生命周期如上圖所示,注意圖中的紅色箭頭腹暖。當(dāng)在onCreate()方法中調(diào)用了setRetainInstance(true)后汇在,F(xiàn)ragment恢復(fù)時(shí)會(huì)跳過(guò)onCreate()和onDestroy()方法,因此不能在onCreate()中放置一些初始化邏輯脏答,切忌糕殉!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市殖告,隨后出現(xiàn)的幾起案子阿蝶,更是在濱河造成了極大的恐慌,老刑警劉巖黄绩,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赡磅,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡宝与,警方通過(guò)查閱死者的電腦和手機(jī)焚廊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)习劫,“玉大人咆瘟,你說(shuō)我怎么就攤上這事》汤铮” “怎么了袒餐?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我灸眼,道長(zhǎng)卧檐,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任焰宣,我火速辦了婚禮霉囚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘匕积。我一直安慰自己盈罐,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布闪唆。 她就那樣靜靜地躺著盅粪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪悄蕾。 梳的紋絲不亂的頭發(fā)上票顾,一...
    開(kāi)封第一講書(shū)人閱讀 51,624評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音帆调,去河邊找鬼奠骄。 笑死,一個(gè)胖子當(dāng)著我的面吹牛贷帮,可吹牛的內(nèi)容都是我干的戚揭。 我是一名探鬼主播诱告,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼撵枢,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了精居?” 一聲冷哼從身側(cè)響起锄禽,我...
    開(kāi)封第一講書(shū)人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎靴姿,沒(méi)想到半個(gè)月后沃但,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡佛吓,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年宵晚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片维雇。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡淤刃,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吱型,到底是詐尸還是另有隱情逸贾,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站铝侵,受9級(jí)特大地震影響灼伤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜咪鲜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一狐赡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嗜诀,春花似錦猾警、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至拂蝎,卻和暖如春穴墅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背温自。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工玄货, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人悼泌。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓松捉,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親馆里。 傳聞我的和親對(duì)象是個(gè)殘疾皇子隘世,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

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

  • Fragment 描述: ??翻譯可以譯為:碎片、片段,Android 3.0開(kāi)始引入fragments 的概念鸠踪;...
    Lost_Robot閱讀 1,694評(píng)論 0 11
  • 啟動(dòng)與銷(xiāo)毀Activity 不同于使用 main() 方法啟動(dòng)應(yīng)用的其他編程范例丙者,Android 系統(tǒng)會(huì)通過(guò)調(diào)用對(duì)...
    安卓Boy閱讀 1,775評(píng)論 3 5
  • 一. Activity的生命周期 下面先上Activity的生命周期圖: 1.Activity生命周期方法: (1...
    Jk_zhuang閱讀 2,097評(píng)論 0 2
  • Activity生命周期 典型生命周期 指在有用戶參與的情況下械媒,Activity經(jīng)歷的生命周期的改變。正常情況下评汰,...
    wangsye閱讀 1,360評(píng)論 0 0
  • 這一次被去,我不再任性 郭法 吵架主儡,是進(jìn)入青春期的我與父母最直接的溝通方式,任性编振,成了我的習(xí)慣缀辩。 一次臭埋,我的鋼筆找不到...
    新我語(yǔ)文閱讀 786評(píng)論 1 3