從新認識Android Activity的生命週期

1、基礎
html

 看了官方文檔以後,本身領悟過來接着翻譯的,因爲第一次的緣由,技術水品乜有跟上,還請你們將就將就。若是你有更好的建議的,但願你能夠提出,若是你以爲哪裏寫的很差的,懇請留下你的指導意見,謝謝。java

1、基礎android

   1.1本身建立的activity必需要繼承類Activity(或其子類)。在activity裏,爲了實現activity各類狀態的切換,你必須實現指定的回調方法。如下是最爲重要的兩個回調方法數據庫

      onCreate():網絡

   這是必須實現的回調方法,啓動一個 activity時會首先調用此方法。所以,在onCreate()的方法體裏,你應該初始化該activity必要的控件。值得注意的是,在這裏你必須調用setContentViewView view)方法去呈現用戶的界面。app

      onPause()ide

   在用戶將要離開activity時調用此方法(指的是此時activity處於半透明狀態且沒有獲取用戶的焦點)。一般在這樣的狀態下,你須要處理用戶數據的提交、動畫處理等操做。佈局

   1.2銷燬activity測試

   你能夠調用finish()方法去銷燬一個activity。一樣得,你能夠調用finishActivity()方法去銷燬一個你剛剛啓動的activity動畫

tips

在多數狀況下,你是不須要顯式地調用finish…()方法去銷燬一個activity。在將要討論到的activity生命週期裏,你能夠知道,Android系統會爲你管理activity的生命週期,因此你並不須要顯式銷燬activity(即調用finish類方法)。顯式地調用finish類方法,會對用戶的體驗產生不利的影響,除非你確實是不但願用戶返回到此activity(界面),纔去顯式調用finish類方法。



2、認識activity的生命週期

21

  Activity的生命週期對它的任務、backstack和與此有關聯的activity有着直接的影響。所以想開發出一個健壯的有彈性的Android程序,你須要學會如何去管理activity的生命週期(即調用各類回調方法)。

  activity的生命週期主要包含一些三種狀態:

1)運行態(Resumedstate

   此時Activity程序顯示在屏幕前臺,而且具備焦點,能夠與用戶的操做進行交互,如向用戶提供信息、捕獲用戶單擊按鈕的事件並作處理。

2)暫停態(PausedState

此時Activity程序失去了焦點,並被其餘處於運行態的otherActivity取代在屏幕顯示,但otherActivity程序並無覆蓋整個屏幕或者具備半透明的效果—此狀態即爲暫停態。處於暫停態的Activity仍然對用戶可見,而且是徹底存活的(此時Activity對象存留在內存裏,保留着全部狀態與成員信息並保持與窗口管理器的鏈接)。若是系統處於內存不足的狀況下,會殺死這個Activity

3)中止態(StoppedState

Activity徹底被另外一個otherActivity覆蓋時(此時otherActivity顯示在屏幕前臺),則處於中止態。處於停滯態的Activity依然是存活的(此時Activity對象依然存留在內存裏,保留着全部的狀態和與成員信息,但沒有與窗口管理器保持鏈接),並且它對用戶是不可見的,若是其餘地方須要內存,系統會銷燬這個Activity



   處於暫停態(PausedState)或者中止態(Stopped State)Activity,系統能夠經過調用finish()方法或者直接終止它的進程來銷燬此Activity(從內存中清楚此Activity對象)。被finish()或者銷燬的Activity再從新打開時,是須要再次初始化此Activity的。


22

當一個Activity從一種狀態轉到另外一種狀態時,會經過調用回調方法來通知這種變化。這些回調方法都是能夠重寫的,你能夠根據程序的的須要來選擇重寫對應的回調方法。如下列出了Activity生命週期裏的基本回調方法:

public class ExampleActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // The activity is being created.
    }
    @Override
    protected void onStart() {
        super.onStart();
        // The activity is about to become visible.
    }
    @Override
    protected void onResume() {
        super.onResume();
        // The activity has become visible (it is now "resumed").
    }
    @Override
    protected void onPause() {
        super.onPause();
        // Another activity is taking focus (this activity is about to be "paused").
    }
    @Override
    protected void onStop() {
        super.onStop();
        // The activity is no longer visible (it is now "stopped")
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // The activity is about to be destroyed.
    }
}

   筆記:在方法體裏,必須先調用父類對應的實現方法super.Xxx(),再執行其餘的操做(如上面代碼所示)。爲了習慣,下面也提供一些代碼來測試一些這些方法的使用,在博客的最後面。


   總的來講,這些回調方法定義了Activity整個生命週期。在生命週期裏經過重寫這些回調方法,,你能夠監控如下下三個嵌套的方法循環。


完整存活的時間:

Activity的完整存活的時間是自第一次調用onCreate()開始,直至調用onDestroy()爲止。ActivityonCreate()中設置全部「全局」狀態以完成初始化,而在onDestroy()中釋放全部系統資源。例如,若是Activity有一個線程在後臺運行從網絡下載數據,它會在onCreate()建立線程,而在 onDestroy()銷燬線程。


可見狀態的時間:

Activity的可見狀態是自onStart()調用開始直到相應的onStop()調用結束。在此期間,用戶能夠在屏幕上看到Activity,儘管它也許並非位於前臺或者也不與用戶進行交互。在這兩個方法之間,咱們能夠保留用來向用戶顯示這個Activity所需的資源。例如,當用戶再也不看見咱們顯示的內容時,咱們能夠在onStart()中註冊一個BroadcastReceiver來監控會影響UI的變化,而在onStop()中來注消。onStart() onStop() 方法能夠隨着應用程序是否爲用戶可見而被屢次調用。


顯示在前臺的時間:

  Activity的前臺顯示是自onResume()調用起,至相應的onPause()調用爲止。在此期間,Activity位於前臺最上面並與用戶進行交互。Activity會常常在暫停和恢復之間進行狀態轉換——例如當設備轉入休眠狀態或者有新的Activity啓動時,將調用onPause() 方法。當Activity得到結果或者接收到新的Intent時會調用onResume() 方法。


2.3

下圖顯示了這三個循環之間的狀態轉換(其中寫在長方形裏的是你能夠用來重寫並實現對應操做的方法)。










































一樣的,如下面的表格來描述生命週期裏的回調方法,幷包含了更加詳細的信息。

方法

描述

是否能夠終止

下一個方法

onCreate()

Activity程序啓動以後會首先調用此方法。在這個方法體裏,你須要完成全部的基礎配置——建立視圖,鏈接數據庫並將數據綁定到list列表中,等等。這個方法會傳遞一個保存了此Activity上一狀態信息的Bundle對象。緊隨其後的方法老是onStart().

不能夠

onStart()


onRestart()

處於中止態的Activity調用此方法,可讓此Activity從新顯示在前臺。

緊隨其後的方法老是onStart()

不能夠

onStart()

onStart()

在此Activity可見(顯示在前臺)以前調用。

若是接着是顯示在前臺,緊隨其後的方法是onResume()若是接下來此Activity被隱藏了,則緊隨其後的方法是onStop()

不能夠

onResume()

onStop()


onResume()

在與用戶進行交互以前調用此方法,這一時刻Activity位於activity棧的棧頂,在等待用戶的操做(輸入數據或點擊按鈕等)。緊隨其後的方法是onPause().

不能夠

onPause()

onPause()

當啓動其餘activity時調用此方法。在這個方法體裏,一般用於提交未保存的數據、中止動畫/視頻和處理其餘佔用CPU資源的程序,等等。同時在這個方法體裏處理的都是一些迅速快捷的操做,由於下一個activity會在onPause()方法執行完以後才能夠在前臺顯示

若是此Activity從新回到前臺顯示,則緊隨其後的方法是onResume();若是此Activity變得不可見了,則緊隨其後的方法是onStop()

能夠

onResume()

onStop()

onStop()

Activity不可見時調用此方法。這個方法的調用時刻是在Activity須要銷燬或者被其餘otherActivity取代且覆蓋此Activity在前臺顯示時調用。

若是此Activity從新顯示在前臺,緊隨其後的方法是onRestart();若是此Activity須要被銷燬,緊隨其後的方法是onDestroy()

能夠

onRestart()

onDestroy()

onDestroy()

Activity被銷燬時調用此方法。這是Activity生命週期裏最後調用的一個方法。這個方法的調用能夠發生在activity調用了finish()方法以後,或者是系統爲了節省空間而銷燬了此Activity的實例。你可使用isFinishing()方法來區分這兩種狀況。

能夠

——


   「是否能夠終止」是指系統是否能夠在此方法執行完後直接銷燬該Activity的實例(沒有再去執行此Activity內的其餘代碼)。如上表所示,onPause(),onStop(),onDestroy()三個方法是能夠終止的。同時從狀態圖(上圖)中能夠知道onPause()方法是這三個方法中第一個調用的,自一個Activity建立開始,直到此Activity終止或銷燬,onPause()是最後一個保證會被調用的方法(如在突發狀況下系統回收內存,onStop()onDestroy()就不會被調用)。所以,你應該在onPause()方法裏保存一些關鍵的數據(如用戶編輯的內容),所謂「關鍵「就是讓你有選擇地去保存一些重要的數據,由於onPause()方法執行時間過長,會延遲下一狀態的切換,進而影響了用戶的體驗。

   附:在上表註明不能夠被終止的方法也可能會被系統終止,不過這一狀況只會在一些極端的狀況下發生。


3、保存Activity的狀態信息

   在前文提到過,處於暫停態的和中止態的Activity,其對應的狀態的狀態與成員信息依然保留在內存裏。那麼這些信息又是如何保存的??咱們又應該如何去利用這些信息??

   在暫停狀態下的activity,因其activity信息完整保存在內存裏且保持與窗口管理器的鏈接,因此能夠直接調用onRestart()方法還原activity

用戶常常會使用返回按鈕返回上一個界面(Activity),用戶固然是但願上一個界面(Activity)和他原來看到或編輯的同樣,在這種狀況下你就須要使用以前已經保存好的狀態信息和成員變量來還原上一個Activity。若要保存一個Activity的狀態信息和成員變量,則須要實現回調方法onSaveInstanceState()

   onSaveInstanceState()會在執行onStoped()方法以前調用,這個方法有一個參數Bundle,能夠以「名稱-值」的形式保存activity的信息(如使用putString(),putInt()方法)。接着在須要還原activity時,系統會調用onCreat()或者OnRestoreInstanceState()這兩個方法都傳入一個以保存了activity信息的Bundle對象,經過提取Bundle對象的信息來恢復activity。若是沒有信息須要保存到Bundle對象,那傳遞給這兩個方法的將是空的Bundle對象(剛開始初始化一個activity時其實就是這種狀況)。以下圖所示:

   其實,即便你沒有實現回調方法onSaveInstanceState()系統也會執行默認的onSaveInstanceState()值得注意的是,系統會爲每一個View組件執行相對應的onSaveInstanceState(),這可使每個組件保存本身相對應的信息。在Android裏,幾乎全部的控件都實現了這個方法,所以在界面產生的可見變化都會自動保存下來,也就能夠還原activity。舉個例子:在EditText輸入的內容或者CheckBox的選擇,都會自動保存下來。而你所須要作的就是爲須要保存信息的控件提供一個id(在XML文件裏的屬性android:id,若是你沒有爲控件提供id,那系統是不會自動保存這些信息的。

下面給出一些例子參考一下onSaveInstanceState()OnRestoreInstanceState()方法的使用:


@Override
    protected void OnSaveInstanceState(Bundle outState)
    {
        outState.PutString("myString", "HelloXamarin.Android OnSaveInstanceState");
        outState.PutBoolean("myBool", true);
        base.OnSaveInstanceState(outState);
    }
    @Override
    protected void OnRestoreInstanceState(Bundle savedState)
    {
        base.OnRestoreSaveInstanceState(savedState);
        var myString =savedState.GetString(amyStringa);
        var myBool =GetBoolean(amyBoola);
    }

   附:若是須要強制控件不保存對應的信息,能夠在佈局文件設置android:saveEnabled = false」,或者使用控件對象的setSaveEnabled()方法。


   儘管系統默認執行onSaveInstanceState()保存對應控件的信息,有時候你須要實現這個方法去保存一些額外的變量。例如:你須要去保存一些在這個activity生命週期裏會改變的變量(指控件信息以外的變量),這些會改變的變量系統是默認不保存的。

   須要注意的是:onSaveInstanceState()方法不保證必定會被調用,因此在這個方法裏你只應該保存一些臨時變量(如UI的狀態),而不要去保存一些須要持久化的數據。相反,你應該在onPaused()方法裏保存須要持久化的數據(例如保存到數據庫裏的數據)。

tips

     Android系統上Back按鈕和Home按鈕的區別,儘管他們均可以導航到另一個otherActivity(能夠是其餘程序的),可他們的做用原理是不同的。在界面(Activity)上點擊Back按鈕,系統會認爲這個Activity已完成其對應的實現邏輯,則調用對應的方法銷燬此Activity;可當點擊Home按鈕時,系統會認爲這個Activity尚未完成對應的邏輯,則系統並不會銷燬這個Activity,而是讓其處於中止態(Stopped State.



4、協調各個Activity

   當ActivityA啓動ActivityB時,這兩個Activity都須要進行狀態的切換。當ActivityB建立的時候,ActivityA會切換到暫停態或者中止態(當ActivityA依然可見是切換到暫停態,不可見則切換到中止態)。假設這兩個Activity共享某些存儲在磁盤的數據,這樣頗有必要去知道,在ActivityB建立完成以前,ActivityA都尚未切換到中止態(StopppedState)

   當兩個Activity處於源於同一個App,又是一個啓動另一個Activity的時候,其生命週期的回調方法是已經定義好的了。一下是這兩個Activity狀態切換個回調方法的調用順序。

  1.執行ActivityAonPaused()方法

  2.依次執行ActivityBonCreate(),onStart(),onResume()方法(此時ActivityB顯示在前臺,得到焦點)。

  3.而後,若是ActivityA變得不可見,則執行ActivityAonStopped()方法。

   根據這些方法調用順序,能夠知道:若是須要在ActivityA保存數據到數據庫,接着讓ActivityB讀取,那麼你應該onPaused()方法裏執行持久化操做,而不是在onStopped()方法裏。



附錄:activityLifecycle的代碼和運行效果圖。

輸出:

輸出(注意其調用的順序):

輸出:


ActivityA的代碼以下:

public class ActivityA extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);
        System.out.println("ActivityA-->onCreate()");
    }
    @Override
    protected void onStart() {
        super.onStart();
        System.out.println("ActivityA-->onStart()");
    }
    @Override
    protected void onRestart() {
        super.onRestart();
        System.out.println("ActivityA-->onRestart()");
    }
    @Override
    protected void onResume() {
        super.onResume();
        System.out.println("ActivityA-->onResume()");
    }
    @Override
    protected void onPause() {
        super.onPause();
        System.out.println("ActivityA-->onPause()");
    }
    @Override
    protected void onStop() {
        super.onStop();
        System.out.println("ActivityA-->onStop()");
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        System.out.println("ActivityA-->onDestroy()");
    }
    public void startDialog(View v) {
        Intent intent = new Intent(ActivityA.this, DialogActivity.class);
        startActivity(intent);
    }
    public void startActivityB(View v) {
        Intent intent = new Intent(ActivityA.this, ActivityB.class);
        startActivity(intent);
    }
                                                                                                                                             
    public void finishActivityA(View v) {
        ActivityA.this.finish();
    }
}
Action


DialogActivity代碼以下:

public class DialogActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_dialog);
        System.out.println("DialogActivity-->onStart()");
    }
                                                                                                  
    @Override
    protected void onStart() {
        super.onStart();
        System.out.println("DialogActivity-->onStart()");
    }
    @Override
    protected void onRestart() {
        super.onRestart();
        System.out.println("DialogActivity-->onRestart()");
    }
    @Override
    protected void onResume() {
        super.onResume();
        System.out.println("DialogActivity-->onResume()");
    }
    @Override
    protected void onPause() {
        super.onPause();
        System.out.println("DialogActivity-->onPause()");
    }
    @Override
    protected void onStop() {
        super.onStop();
        System.out.println("DialogActivity-->onStop()");
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        System.out.println("DialogActivity-->onDestroy()");
    }
                                                                                                  
    public void finishDialog(View v) {
        DialogActivity.this.finish();
    }
                                                                                                  
}

其餘代碼相似,就不一一張貼了。

相關文章
相關標籤/搜索