Activity的生命周期

1.正常情況下的生命周期

1.onCreate:onDestory配對,表示Activity被創(chuàng)建,這是生命周期的第一個方法。在這方法中可以做一個初始化的工作(比如加載布局資源,初始化activity所需要的數(shù)據(jù)等),耗時的工作在異步線程上完成。

2.onRestart:表示Activity正在重新啟動一般情況下,在當前Actiivity從不可見重新變?yōu)榭梢姞顟B(tài)時onRestart就會被調(diào)用。這種請求一般都是用戶行為所導(dǎo)致的,比如用戶按下Home鍵切換到桌面或者打開了一個新的Activity(這時當前的Activity會暫停,也就是onPause和onStop被執(zhí)行),接著用戶回到了這個Activity就會出現(xiàn)這種情況。

3.onStart:onStop配對,表示Activity正在被啟動,并且即將開始。但是這個時候要注意他與onResume的區(qū)別,兩者都標識Avtivity可見,但是onStartActivity還在加載其他內(nèi)容,正在像我們展示,用戶還無法看到,即無法交互。

4.onResume:onPause配對,表示Activity已經(jīng)創(chuàng)建完成,并可以開始活動了,這個時候用戶可以看到界面,并且即將與用戶交互 (完成該周期之后便可以響應(yīng)用戶的交互事件了)。

5.onPause:onResume配對,表示Activity正在暫停,正常情況下,onStop接著就會被調(diào)用,在特殊情況下,如果這個時候用戶快速的再回到當前Activity,那么onResume會被調(diào)用(極端情況),一般來說,在onPause這個生命周期狀態(tài)下可以做一些數(shù)據(jù)存儲,停止動畫的工作,但是不能太耗時,,如果是由于啟動新的Activity而喚醒的該狀態(tài),那會影響到新Activity的顯示,原因是onPause必須執(zhí)行完,新的ActivityonResume才會執(zhí)行。

6.onStop:onStart配對,表示Activity即將停止,可以做一些稍微重量級的回收工作,同樣也不能太耗時(可以比onPause稍微好一點)。

7.onDestroy:與onCreate配對,表示Activity即將被銷毀,這是Activity生命周期的最后一個回調(diào),我們可以做一些回收工作和最終的資源釋放(如ServiceBroadReceiver、Map等)。

正常情況下,Activity的常用生命周期就是上面的7個,下圖更加詳細的描述的各種生命周期的切換過程:

9KP_EEF`(~_VRX8R2BH07AL.png

這里要說的是,從上圖我們可以看到一個現(xiàn)象:
onStartonStop、onResumeonPause是配對的。兩種Activity回到前臺的方式,從onPause狀態(tài)回到前臺會走到onResume狀態(tài),從onStop狀態(tài)回到前臺會到onStart狀態(tài),這是從是否可見和是否在前臺來說的。從是否可見來說,onStartonStop是配對的;從是否在前臺來說,onResumeonPause是配對的。

我們來看看正常情況下生命周期的系統(tǒng)日志:

03-23 00:15:52.970 32278-32278/com.example.david.lifecircle E/TAG: onCreate() is invoked!
03-23 00:15:52.971 32278-32278/com.example.david.lifecircle E/TAG: onStart() is invoked!
03-23 00:15:52.971 32278-32278/com.example.david.lifecircle E/TAG: onResume() is invoked!
03-23 00:15:55.858 32278-32278/com.example.david.lifecircle E/TAG: onPause() is invoked!
03-23 00:16:02.573 32278-32278/com.example.david.lifecircle E/TAG: onRestart() is invoked!
03-23 00:16:02.573 32278-32278/com.example.david.lifecircle E/TAG: onStart() is invoked!
03-23 00:16:02.573 32278-32278/com.example.david.lifecircle E/TAG: onResume() is invoked!

2.異常情況下的生命周期

一般正常情況的聲明周期就像上面所說的一樣,但是因為Android本身內(nèi)存或者其他的一些情況會使得Activity不按照正常的生命周期。比如當資源配置發(fā)生改變、系統(tǒng)內(nèi)存不足時,Activity就會被殺死。下面分析這兩種常見的情況。
情況1:資源相關(guān)的系統(tǒng)配置發(fā)生改變導(dǎo)致Activity被殺死并重新創(chuàng)建
理解這個問題,我們首先要對系統(tǒng)的資源加載機制有一定了解,不過這里我不分析系統(tǒng)資源加載機制了(因為我也不怎么懂)。簡單說明一下,就像是我們把一張圖片放在drawable目錄之后,就可以通過Resources去獲取這張圖片。同時為了兼容不同的設(shè)備,我們還可能需要在其他的一些目錄放置不同的圖片,比如 drawable-mdpi、drawable-hdpi等。這樣,當應(yīng)用程序啟動時,系統(tǒng)就會根據(jù)當前設(shè)備的情況去加載合適的Resource資源,比如說橫屏和豎屏的手機會拿到兩張不同的圖片(設(shè)定了landscapeportrait狀態(tài)下的圖片)。
如果說,當前Activity處于豎屏狀態(tài),如果突然旋轉(zhuǎn)屏幕,由于系統(tǒng)配置發(fā)生了改變,在默認情況下,Activity就會被銷毀并重新創(chuàng)建(當然我們也可以組織系統(tǒng)重新創(chuàng)建,具體就在Mainfest中申明android:Configchanges=屬性即可)。

異常情況下的調(diào)用流程:
1.調(diào)用onSaveInstance保存當前Activity狀態(tài)。注意,它與onPause方法沒有先后之分。
2.調(diào)用onStop方法做后續(xù)處理。
3.調(diào)用onDestroy方法銷毀當前活動。
4.重新onCreate該活動。
5.調(diào)用onStart方法之后,再調(diào)用onRestoreInstance方法加載保存的數(shù)據(jù)。
6.接下來就與正常的一樣了,調(diào)用onResume,然后運行。

我們來看一下生命周期異常運行的系統(tǒng)日志:
03-23 00:19:23.480 26457-26457/com.example.david.lifecircle E/TAG: onCreate() is invoked!
03-23 00:19:23.481 26457-26457/com.example.david.lifecircle E/TAG: onStart() is invoked!
03-23 00:19:23.481 26457-26457/com.example.david.lifecircle E/TAG: onResume() is invoked!
03-23 00:19:51.323 26457-26457/com.example.david.lifecircle E/TAG: onPause() is invoked!
03-23 00:19:51.324 26457-26457/com.example.david.lifecircle E/TAG: onSaveInstanceState() is invoked!  Save Text = Save Data
03-23 00:19:51.478 26457-26457/com.example.david.lifecircle E/TAG: onCreate() is invoked!
03-23 00:19:51.488 26457-26457/com.example.david.lifecircle E/TAG: onStart() is invoked!
03-23 00:19:51.490 26457-26457/com.example.david.lifecircle E/TAG: onRestoreInstanceState() is invoked!  Recover Text = Save Data
03-23 00:19:51.490 26457-26457/com.example.david.lifecircle E/TAG: onResume() is invoked!

情況2:資源內(nèi)存不足導(dǎo)致低優(yōu)先級的Activity被殺死

這種情況不好模擬,但是其數(shù)據(jù)存儲和恢復(fù)過程和情況1完全一致,這里簡單的描述一下Activity的優(yōu)先級情況。Activity的優(yōu)先級從高到低可以大致分為一下三種:

(1)前臺Activity——正在和用戶交互的Activity,優(yōu)先級最高。
(2)可見但非前臺Activity——比如Activity中彈出了一個對話框,導(dǎo)致Activity可見但無法和用戶直接交互。
(3)后臺Activity——已經(jīng)被暫?;蛘咄V沟?code>Activity,優(yōu)先級最底。

當系統(tǒng)內(nèi)存不足的時候,系統(tǒng)就會按照上述優(yōu)先級從低到高來殺死目標Activity。并在后續(xù)通過onSaveInstanceonRestoreInstance來存儲和恢復(fù)數(shù)據(jù)。
特別提醒的是:如果一個進程中沒有四大組件(ActivityService、ContentProviderBroadCastReceiver)。那么這個進程就會很快被殺死,因此一些后臺工作不適合脫離四大組件而獨立運行在后臺中,否則很容易被殺死。一般是將后臺工作放入Service中從而保證進程有一定的優(yōu)先級,這樣才不會被系統(tǒng)輕易殺死

三、生命周期的使用

1.常見的生命周期有關(guān)問題:

1.onStartonResume、onPauseonStop從描述上看來差不多,但是他們?yōu)槭裁磿珠_呢?有什么不同?
2.兩個Activity AB,從A中啟動B,那么BonResumeAonPause哪個會先執(zhí)行呢?
3.onSaveInstanceonRestoreInstance是任何情況下都可以使用的嘛?所有的保存數(shù)據(jù)和恢復(fù)的操作都可以在這對方法中執(zhí)行?
4.如上面所說,如何使得在系統(tǒng)配置放生改變后,Activity不被重新創(chuàng)建呢?

2.解析

1、 onStartonResume、onPauseonStop這兩對看起來是差不多,而且很多時候都會同時調(diào)用onPauseonStop,然后回到onStart、onResume。但是在一些比較特殊的情況下就不一樣了。我們舉兩種情況,
第一種:前臺彈出了一個Dialog,那么這個Dialog的作用只是提醒用戶或者讓用戶輸入一個信息等就完畢了,這是一個比較輕量級的任務(wù);
第二種:重新啟動另一個Activity界面,轉(zhuǎn)到另一個模塊。這時新啟動的Activity就不是一個臨時或者輕量級的任務(wù)了。
這兩種情況,第一種一般很快就會返回當前Activity,不會太耗時;第二種可能會很久,在這段時間內(nèi)系統(tǒng)可能需要啟動其他的應(yīng)用,那么就會產(chǎn)生內(nèi)存緊張的問題。所以,我認為是要區(qū)分這兩種情況,才會加入這兩對方法。在第一種情況下,可以在onPause中做一些較輕微的數(shù)據(jù)存儲,因為一般很快就會回到當前Activity;第二種情況下,適合在onStop中做一些較重量級的存儲。除此之外,我想不到其他的使用了。

2、這個問題可以從源碼中得到解答。不過源碼太復(fù)雜,涉及底層太多(AMSBinder、ActivityStackActivityThread等)。不過可以直接調(diào)用生命周期,輸出系統(tǒng)日志來得到解答。從下面的日志我們可以看出,的確是要等到A活動的onPause方法之后B才能執(zhí)行(這里onCreate沒有輸出日志):

03-23 01:02:31.339 32382-32382/com.example.david.lifecircle E/MainActivity: onCreate() is invoked!
03-23 01:02:31.341 32382-32382/com.example.david.lifecircle E/MainActivity: onStart() is invoked!
03-23 01:02:31.341 32382-32382/com.example.david.lifecircle E/MainActivity: onResume() is invoked!
03-23 01:04:04.005 32382-32382/com.example.david.lifecircle E/MainActivity: onPause() is invoked!
03-23 01:04:04.047 32382-32382/com.example.david.lifecircle E/SecondActivity: onStart() is invoked!
03-23 01:04:04.047 32382-32382/com.example.david.lifecircle E/SecondActivity: onResume() is invoked!

3、 onSaveInstanceonRestoreInstance是只有Activity異常銷毀的時候才會調(diào)用的,所以這里一般執(zhí)行的是Activity異常銷毀時需要保存和恢復(fù)的數(shù)據(jù);onSaveInstanceonRestoreInstance方法還可以判斷Activity是否被重建,但正常情況下是不會調(diào)用的。所以正常情況下,還是應(yīng)該在onPauseonStop方法中保存數(shù)據(jù)。

4、上面提到,我們可以在AndroidMainfest.xml里,對< activity />增加一個android:configChanges屬性,來指定在哪些配置改變的情況下Activity不需要重建。如下所示:

android:configChanges="orientation|screenSize"http://界面方向以及大小的改變不需要重建

我們在AndroidMainfest.xml做如下申明:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.david.lifecircle">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
            android:configChanges="orientation|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".SecondActivity"></activity>
    </application>

</manifest>

MainActivity中的部分代碼:

 @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        Log.e("MainActivity","onConfigurationChanged() is invoked!"+newConfig.orientation);
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.e("MainActivity","onPause() is invoked!");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.e("MainActivity","onResume() is invoked!");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.e("MainActivity","onStart() is invoked!");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.e("MainActivity","onRestart() is invoked!");
    }

點擊屏幕旋轉(zhuǎn),然后來看一下系統(tǒng)日志輸出:

03-23 01:14:11.357 10361-10361/com.example.david.lifecircle E/MainActivity: onCreate() is invoked!
03-23 01:14:11.359 10361-10361/com.example.david.lifecircle E/MainActivity: onStart() is invoked!
03-23 01:14:11.359 10361-10361/com.example.david.lifecircle E/MainActivity: onResume() is invoked!
03-23 01:14:28.140 10361-10361/com.example.david.lifecircle E/MainActivity: onConfigurationChanged() is invoked!2
03-23 01:14:38.294 10361-10361/com.example.david.lifecircle E/MainActivity: onConfigurationChanged() is invoked!1
03-23 01:14:47.531 10361-10361/com.example.david.lifecircle E/MainActivity: onConfigurationChan

我們發(fā)現(xiàn),屏幕旋轉(zhuǎn)之后,并沒有重新調(diào)用生命周期,說明活動并沒有被重建。configChanges屬性還有許多的值,如:mcc\mnc\local\touchscreen\keyboard等等。

最后用一個實際的例子來說明Activity的各個生命周期。假設(shè)有一個程序由2個Activity`` AB組成,A是這個程序的啟動界面。當用戶啟動程序時,Process和默認的Task分別被創(chuàng)建,接著A被壓入到當前的Task中,依次執(zhí)行了 onCreate, onStart, onResume事件被呈現(xiàn)給了用戶;此時用戶選擇A中的某個功能開啟界面B,界面B被壓入當前Task遮蓋住了A,AonPause事件執(zhí)行,BonCreate, onStart, onResume事件執(zhí)行,呈現(xiàn)了界面B給用戶;用戶在界面B操作完成后,使用Back鍵回到界面A,界面B不再可見,界面BonPause, onStop, onDestroy執(zhí)行,AonResume事件被執(zhí)行,呈現(xiàn)界面A給用戶。此時突然來電,界面AonPause事件被執(zhí)行,電話接聽界面被呈現(xiàn)給用 戶,用戶接聽完電話后,又按了Home鍵回到桌面,打開另一個程序“聯(lián)系人”,添加了聯(lián)系人信息又做了一些其他的操作,此時界面A不再可見,其 onStop事件被執(zhí)行,但并沒有被銷毀。此后用戶重新從菜單中點擊了我們的程序,由于A和其所在的進程和Task并沒有被銷毀,AonRestartonStart事件被執(zhí)行,接著AonResume事件被執(zhí)行,A又被呈現(xiàn)給了用戶。用戶這次使用完后,按Back鍵返回到桌面,AonPause, onStop被執(zhí)行,隨后AonDestroy被執(zhí)行,由于當前Task中已經(jīng)沒有任何ActivityA所在的Process的重要程度被降到很 低,很快A所在的Process被系統(tǒng)結(jié)束
常見的例子

情形一、一個單獨的Activity的正常的生命過程是這樣的:onCreate->onStart->onPause->onStop->onDestroy。例如:運行一個Activit,進行了一些簡單操作(不涉及頁面的跳轉(zhuǎn)等),然后按返回鍵結(jié)束。

情形二、有兩個Activity(a和b),一開始顯示a,然后由a啟動b,然后在由b回到a,這時候a的生命過程應(yīng)該是怎么樣的呢(a被b完全遮蓋)?

a經(jīng)歷的過程為onCreate->onStart->onResume->onPause->onStop->onRestart->onStart->onResume。這個過程說明了圖中,如果Activity完全被其他界面遮擋時,進入后臺,并沒有完全銷毀,而是停留在onStop狀態(tài),當再次進入a時,onRestart->onStart->onResume,又重新恢復(fù)。

情形三、基本情形同二一樣,不過此時a被b部分遮蓋(比如給b添加個對話框主題 android:theme=”@android:style/Theme.Dialog”)

a經(jīng)歷的過程是:onCreate->onStart->onResume->onPause->onResume

所以當Activity被部分遮擋時,Activity進入onPause,并沒有進入onStop,從Activity2返回后,執(zhí)行了onResume

情形四、 打開程序,啟動a,點擊a,啟動AlertDialog,按返回鍵從AlertDialog返回。

a經(jīng)歷的過程是:onCreate->onStart->onResume

當啟動和退出Dialog時,Activity的狀態(tài)始終未變,,因為Dialog實際上時一個View,它是屬于某一個Activity的,因此如果Dialog顯示在當前Activity之前時不會影響到Activity的生命周期的。但是如果是其他ActivityDialog彈出那么就會觸發(fā)onPause()方法的執(zhí)行。

摘自 https://blog.csdn.net/woshimalingyi/article/details/50961380

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

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

  • 啟動與銷毀Activity 不同于使用 main() 方法啟動應(yīng)用的其他編程范例,Android 系統(tǒng)會通過調(diào)用對...
    安卓Boy閱讀 1,879評論 3 5
  • 這是我第三遍看《Android開發(fā)藝術(shù)探索》這本書了,從第一遍看的云里霧里,第二遍略微明白之后,我決定看第三遍,并...
    陳添閱讀 967評論 2 8
  • 一本android開發(fā)程序員必讀的一本書,感謝任玉剛大佬的分享 一、Activity的生命周期全面分析 典型情況下...
    kongjn閱讀 632評論 1 3
  • 啟動與銷毀Activity 不同于使用 main() 方法啟動應(yīng)用的其他編程范例,Android 系統(tǒng)會通過調(diào)用對...
    mouekz閱讀 718評論 0 0
  • 時間過得飛快一轉(zhuǎn)眼一年時間就過去了,先小小的感嘆下啊?;氐秸},最近在投簡歷看看是否有更好的機會和平臺,很高興得到...
    Elder閱讀 1,295評論 3 5

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