Activity在橫豎屏切換、按BACK、按HOME鍵時執行的生命週期方法總結

Activity的生命週期模型在Google提供的官方文檔上有比較詳細的一個圖示

 

複製代碼
public class HelloActivity extends Activity {
    public static final String TAG = "HelloActivity";
    /** 
     * 第一個被運行的方法
     * 初始化頁面
     * Bundle恢復上次的狀態 
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Log.v(TAG, "onCreate");
    }
    
    /**
     * 從onStop回到Activity的時候會執行
     * 按HOME鍵的時候會執行onStop,重新回到程序會執行這個方法
     */
    @Override
    protected void onRestart() {
        super.onRestart();
        Log.v(TAG, "onRestart");
    }
    
    /**
     * 在onCreate,onRestart後面執行
     */
    @Override
       protected void onStart() {
           super.onStart();
           Log.v(TAG, "onStart");
       }
    
    /**
     * 在onStart後面執行,執行這個方法後這個Activity就處於全部Activity堆棧的最上面
     * 進入用戶可見可操作的狀態
     */
    @Override
    protected void onResume() {
        super.onResume();
        Log.v(TAG, "onResume");
    }
    
    /**
     * 當其他Activity啓動時這個方法會執行
     * 按HOME和BACK都會執行這個方法
     * 最好在這個方法中提交或者保存數據,因爲很有可能再也不會回到這個activity中。
     * 這個方法最好不要執行太長時間,因爲下個activity開始執行前會等待這個方法返回。
     */
    @Override
    protected void onPause() {
        super.onPause();
        Log.v(TAG, "onPause");
    }

    /**
     * activity很久沒被顯示,要被銷燬,系統資源缺乏,都會調用這個方法
     * 按HOME和BACK都會執行這個方法
     */
    @Override
    protected void onStop() {
        super.onStop();
        Log.v(TAG, "onStop");
    }

    /**
     * 調用finish方法,或者系統回收資源時調用
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.v(TAG, "onDestroy");
    }
    
}
複製代碼
PS:
  •  手機應用的大多數情況下我們只能在手機上看到一個程序的一個界面,用戶除了通過程序界面上的功能按鈕來在不同的窗體間切換,還可以通過Back鍵和 Home鍵來返回上一個窗口,而用戶使用Back或者Home的時機是非常不確定的,任何時候用戶都可以使用Home或Back來強行切換當前的界面。
  • HOME鍵的執行順序:onPause->onStop->onRestart->onStart->onResume
  • BACK鍵的順序: onPause->onStop->onDestroy->onCreate->onStart->onResume
  • onPause不要做太耗時的工作

    各種方法的詳解
    1. void onCreate(Bundle savedInstanceState) 

    當Activity被第首次加載時執行。我們新啓動一個程序的時候其主窗體的onCreate事件就會被執行。如果Activity被銷燬後 (onDestroy後),再重新加載進Task時,其onCreate事件也會被重新執行。注意這裏的參數 savedInstanceState(Bundle類型是一個鍵值對集合,大家可以看成是.Net中的Dictionary)是一個很有用的設計,由於 前面已經說到的手機應用的特殊性,一個Activity很可能被強制交換到後臺(交換到後臺就是指該窗體不再對用戶可見,但實際上又還是存在於某個 Task中的,比如一個新的Activity壓入了當前的Task從而“遮蓋”住了當前的 Activity,或者用戶按了Home鍵回到桌面,又或者其他重要事件發生導致新的Activity出現在當前Activity之上,比如來電界面), 而如果此後用戶在一段時間內沒有重新查看該窗體(Android通過長按Home鍵可以選擇最近運行的6個程序,或者用戶直接再次點擊程序的運行圖標,如 果窗體所在的Task和進程沒有被系統銷燬,則不用重新加載Process, Task和Task中的Activity,直接重新顯示Task頂部的Activity,這就稱之爲重新查看某個程序的窗體),該窗體連同其所在的 Task和Process則可能已經被系統自動銷燬了,此時如果再次查看該窗體,則要重新執行 onCreate事件初始化窗體。而這個時候我們可能希望用戶繼續上次打開該窗體時的操作狀態進行操作,而不是一切從頭開始。例如用戶在編輯短信時突然來 電,接完電話後用戶又去做了一些其他的事情,比如保存來電號碼到聯繫人,而沒有立即回到短信編輯界面,導致了短信編輯界面被銷燬,當用戶重新進入短信程序 時他可能希望繼續上次的編輯。這種情況我們就可以覆寫Activity的void onSaveInstanceState(Bundle outState)事件,通過向outState中寫入一些我們需要在窗體銷燬前保存的狀態或信息,這樣在窗體重新執行onCreate的時候,則會通過 savedInstanceState將之前保存的信息傳遞進來,此時我們就可以有選擇的利用這些信息來初始化窗體,而不是一切從頭開始。 

    2. void onStart() 

    onCreate事件之後執行。或者當前窗體被交換到後臺後,在用戶重新查看窗體前已經過去了一段時間,窗體已經執行了onStop事件,但是窗 體和其所在進程並沒有被銷燬,用戶再次重新查看窗體時會執行onRestart事件,之後會跳過onCreate事件,直接執行窗體的onStart事 件。 

    3. void onResume() 

    onStart事件之後執行。或者當前窗體被交換到後臺後,在用戶重新查看窗體時,窗體還沒有被銷燬,也沒有執行過onStop事件(窗體還繼續存在於Task中),則會跳過窗體的onCreate和onStart事件,直接執行onResume事件。 

    4. void onPause() 

    窗體被交換到後臺時執行。 


    5. void onStop() 

    onPause事件之後執行。如果一段時間內用戶還沒有重新查看該窗體,則該窗體的onStop事件將會被執行;或者用戶直接按了Back鍵,將該窗體從當前Task中移除,也會執行該窗體的onStop事件。 

    6. void onRestart() 

    onStop事件執行後,如果窗體和其所在的進程沒有被系統銷燬,此時用戶又重新查看該窗體,則會執行窗體的onRestart事件,onRestart事件後會跳過窗體的onCreate事件直接執行onStart事件。 

    7. void onDestroy() 

    Activity被銷燬的時候執行。在窗體的onStop事件之後,如果沒有再次查看該窗體,Activity則會被銷燬。 

    最後用一個實際的例子來說明Activity的各個生命週期。假設有一個程序由2個Activity A和B組成,A是這個程序的啓動界面。當用戶啓動程序時,Process和默認的Task分別被創建,接着A被壓入到當前的Task中,依次執行了 onCreate, onStart, onResume事件被呈現給了用戶;此時用戶選擇A中的某個功能開啓界面B,界面B被壓入當前Task遮蓋住了A,A的onPause事件執行,B的 onCreate, onStart, onResume事件執行,呈現了界面B給用戶;用戶在界面B操作完成後,使用Back鍵回到界面A,界面B不再可見,界面B的onPause, onStop, onDestroy執行,A的onResume事件被執行,呈現界面A給用戶。此時突然來電,界面A的onPause事件被執行,電話接聽界面被呈現給用 戶,用戶接聽完電話後,又按了Home鍵回到桌面,打開另一個程序“聯繫人”,添加了聯繫人信息又做了一些其他的操作,此時界面A不再可見,其 onStop事件被執行,但並沒有被銷燬。此後用戶重新從菜單中點擊了我們的程序,由於A和其所在的進程和Task並沒有被銷燬,A的onRestart 和onStart事件被執行,接着A的onResume事件被執行,A又被呈現給了用戶。用戶這次使用完後,按Back鍵返回到桌面,A的 onPause, onStop被執行,隨後A的onDestroy被執行,由於當前Task中已經沒有任何Activity,A所在的Process的重要程度被降到很 低,很快A所在的Process被系統結束
  • 常見的例子

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

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

a經歷的過程爲onCreate->onStart->onResume->onPause->onStop->onRestart->onStart->onResume。這個過程說明了圖中,如果Activity完全被其他界面遮擋時,進入後臺,並沒有完全銷燬,而是停留在onStop狀態,當再次進入a時,onRestart->onStart->onResume,又重新恢復。 

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

a經歷的過程是:onCreate->onStart->onResume->onPause->onResume 

所以當Activity被部分遮擋時,Activity進入onPause,並沒有進入onStop,從Activity2返回後,執行了onResume 

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

a經歷的過程是:onCreate->onStart->onResume 

當啓動和退出Dialog時,Activity的狀態始終未變,可見,Dialog實際上屬於Acitivity內部的界面,不會影響Acitivty的生命週期。

發佈了8 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章