天天看點

Android學習之詳解Activity的生命周期

Activity

Activity作為Android的四大元件之一,可見其地位非同尋常,官網介紹:

移動應用體驗與桌面體驗的不同之處在于,使用者與應用的互動并不總是在同一位置開始,而是經常以不确定的方式開始。例如,如果您從主螢幕打開電子郵件應用,可能會看到電子郵件清單,如果您通過社交媒體應用啟動電子郵件應用,則可能會直接進入電子郵件應用的郵件撰寫界面。

Activity類的目的就是促進這種範式的實作。當一個應用調用另一個應用時,調用方應用會調用另一個應用中的 Activity,而不是整個應用。通過這種方式,Activity 充當了應用與使用者互動的入口點。您可以将 Activity 實作為Activity類的子類。

下面是關于Activity類的文檔說明:

Android學習之詳解Activity的生命周期

更多詳情可見官方API文檔:Activity類

Activity類是 Android 應用的關鍵元件,而 Activity 的啟動群組合方式則是該平台應用模型的基本組成部分。在程式設計範式中,應用是通過

main()

方法啟動的,而 Android 系統與此不同,它會調用與其生命周期特定階段相對應的特定回調方法來啟動 Activity執行個體中的代碼。

擴充:Activity / ActionBarActivity / AppCompatActivity的差別:

Activity

是大佬就不用說啦,後面這兩個

(ActionBarActivity / AppCompatActivity)

都是為了低版本相容而提出來的,它們都在v7包下, ActionBarActivity已被廢棄,從名字就知道,ActionBarActivity在5.0後,被Google棄用了,

AppCompatActivity

其實是

ActionBarActivity

的替代,預設帶标題。而我們現在在Android Studio建立一個Activity預設繼承的會是:

AppCompatActivity

! 當然你也可以改成

Activity

,沒什麼影響的,看個人喜好。

在開發Android應用過程中,通常Activity(活動)是與使用者互動的接口,它提供了一個使用者完成相關操作的視窗。當我們在開發中建立Activity後,通過調用setContentView(View)方法來給該Activity指定一個布局界面,而這個界面就是提供給使用者互動的接口。Android系統中是通過Activity棧的方式來管理Activity的,而Activity自身則是通過生命周期的方法來管理自己的建立與銷毀,So,下面我将講一下關于Activity的生命周期。

Activity的生命周期

先上圖,官方給出的Activity 生命周期的簡化圖:

Android學習之詳解Activity的生命周期

當使用者浏覽、退出和傳回到Android應用時,應用中的 Activity 執行個體會在其生命周期的不同狀态間轉換。Activity 類會提供許多回調,這些回調會讓 Activity 知曉某個狀态已經更改:系統正在建立、停止或恢複某個 Activity,或者正在銷毀該 Activity 所在的程序。

為了在 Activity 生命周期的各個階段之間導航轉換,Activity 類提供六個核心回調:

onCreate()

onStart()

onResume()

onPause()

onStop()

onDestroy()

。當 Activity 進入新狀态時,系統會調用其中每個回調。
  • onCreate()

    代碼必須實作此回調

    ,它會在系統首次建立 Activity 時觸發。Activity 會在建立後進入“已建立”狀态。它是生命周期第一個調用的方法,在該方法中做一些初始化的操作,如通過setContentView設定界面布局的資源,初始化所需要的元件資訊等,這些基本應用啟動邏輯在 Activity 的整個生命周期中隻應發生一次。
  • onStart()

    當上面的

    onCreate()

    方法執行完成之後,Activity會 進入“已開始”狀态,系統會調用此回調。表示Activity正在啟動,這是在 Activity 即将對使用者可見之前調用的,此時的Activity已處于可見狀态,隻是還沒有在前台顯示,是以無法與使用者進行互動。

    onStart()

    方法會非常快速地完成,Activity 不會一直處于“已開始”狀态。一旦此回調結束,Activity 便會進入“已恢複”狀态,系統将調用

    onResume()

    方法。
  • onResume()

    Activity 會在進入“已恢複”狀态時來到前台,然後系統調用

    onResume()

    回調,此時Activity 處于 Activity 堆棧的頂層,也可以說明Activity已在前台可見,并具有使用者輸入焦點,可與使用者互動了。這是應用與使用者互動的狀态,應用會一直保持這種狀态,直到某些事件發生,讓焦點遠離應用。此類事件包括接到來電、使用者導航到另一個 Activity,或裝置螢幕關閉。

    當Activity停止後(

    onPause()

    方法或者

    onStop()

    方法被調用),重新回到前台時也會調用

    onResume()

    方法,是以我們也可以在

    onResume()

    方法中初始化一些資源,比如

    重新初始化

    onPause()

    或者

    onStop()

    方法中

    釋放的資源

  • onPause()

    系統将此方法視為使用者将要離開 Activity 的第一個标志(盡管這并不總是意味着 Activity 會被銷毀)。此方法表示 Activity 不再位于前台(盡管在使用者處于多視窗模式時 Activity 仍然可見)。

    在 Android 7.0(API 級别 24)或更高版本中,有多個應用在多視窗模式下運作。無論何時,都隻有一個應用(視窗)可以擁有焦點,是以系統會暫停所有其他應用。

    onPause()

    執行非常簡單,而且不一定要有足夠的時間來執行儲存操作。是以,不應使用

    onPause()

    來儲存應用或使用者資料、進行網絡調用或執行資料庫事務。因為在該方法完成之前,此類工作可能無法完成。相反,應在

    onStop()

    期間執行高負載的關閉操作。 正常情況下,

    onStop()

    方法會緊接着被回調的,但是有一種極端情況,

    onPause()

    方法執行後直接執行了

    onResume()

    方法,這可能是使用者操作使目前Activity退居背景後,又迅速地再次回到到目前的Activity,此時

    onResume()

    方法就會被回調。
  • onStop()

    如果 Activity 不再對使用者可見,說明其已進入“已停止”狀态,是以系統将調用

    onStop()

    回調。在

    onStop()

    方法中,應用應釋放或調整在應用對使用者不可見時的無用資源。例如,應用可以暫停動畫效果,或從精确位置更新切換到粗略位置更新。使用

    onStop()

    而非

    onPause()

    可確定與界面相關的工作繼續進行,即使使用者在多視窗模式下檢視您的 Activity 也能如此。 還可以 執行 CPU 相對密集的關閉操作。例如,如果無法找到更合适的時機來将資訊儲存到資料庫,可以在

    onStop()

    期間執行此操作。

    進入“已停止”狀态後,Activity 要麼傳回與使用者互動,要麼結束運作并消失。如果 Activity 傳回,系統将調用

    onRestart()

    。如果 Activity 結束運作,系統将調用

    onDestroy()

備注:

AlertDialog和PopWindow是不會觸發上述

onPause()

onStop()

兩個回調方法的。
  • onRestart()

    在Activity被停止後再次啟動時調用(即螢幕熄滅後再次回到app,按下home鍵後再次回到app),而後面會調用

    onStart()

    方法。
  • onDestroy()

    銷毀 Activity 之前,系統會先調用

    onDestroy()

    。系統調用此回調的原因:

    1、Activity 即将結束(由于使用者徹底關閉 Activity 或由于系統為 Activity 調用 finish())

    2、由于配置變更(例如裝置旋轉或多視窗模式),系統暫時銷毀 Activity

    可以使用 isFinishing() 方法區分這兩種情況。

    如果 Activity 即将結束,

    onDestroy()

    是 Activity 收到的最後一個生命周期回調。如果由于配置變更而調用

    onDestroy()

    ,系統會立即建立 Activity 執行個體,然後在新配置中為新執行個體調用

    onCreate()

    onDestroy()

    回調應釋放先前的回調(例如

    onStop()

    )尚未釋放的所有資源。

注意:上面這些都是回調方法,我們不能夠去調用,我們能做的隻是重寫方法裡面的内容,什麼時候去調用是由Activity所決定的。我們可以調用finish()方法,它可用于關閉某個Activity。

代碼驗證

第一個Activity:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "Main";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button bt = findViewById(R.id.bt_main2);
        bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this, Main2Activity.class));
            }
        });

        Log.d(TAG, "onCreate: ------> MainActivity進入“已建立”狀态!");
    }

    @Override
    protected void onRestart() {
        super.onRestart();

        Log.d(TAG, "onRestart: ------> “已停止”狀态的MainActivity即将重新開機!");
    }

    @Override
    protected void onStart() {
        super.onStart();

        Log.d(TAG, "onStart: ------> MainActivity進入“已開始”狀态!");
    }

    @Override
    protected void onResume() {
        super.onResume();

        Log.d(TAG, "onResume: ------> MainActivity進入“應用與使用者互動”狀态!");
    }

    @Override
    protected void onPause() {
        super.onPause();

        Log.d(TAG, "onPause: ------> MainActivity進入“已暫停”狀态!");
    }

    @Override
    protected void onStop() {
        super.onStop();

        Log.d(TAG, "onStop: ------> MainActivity進入“已停止”狀态!");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        Log.d(TAG, "onDestroy: ------> MainActivity進入“已銷毀”狀态!");
    }
}

           

第二個Activity:

public class Main2Activity extends AppCompatActivity {

    private static final String TAG = "Main";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        Log.d(TAG, "onCreate: ------> Main2Activity進入“已建立”狀态!");
    }

    @Override
    protected void onRestart() {
        super.onRestart();

        Log.d(TAG, "onRestart: ------> “已停止”狀态的Main2Activity即将重新開機!");
    }

    @Override
    protected void onStart() {
        super.onStart();

        Log.d(TAG, "onStart: ------> Main2Activity進入“已開始”狀态!");
    }

    @Override
    protected void onResume() {
        super.onResume();

        Log.d(TAG, "onResume: ------> Main2Activity進入“應用與使用者互動”狀态!");
    }

    @Override
    protected void onPause() {
        super.onPause();

        Log.d(TAG, "onPause: ------> Main2Activity進入“已暫停”狀态!");
    }

    @Override
    protected void onStop() {
        super.onStop();

        Log.d(TAG, "onStop: ------> Main2Activity進入“已停止”狀态!");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        Log.d(TAG, "onDestroy: ------> Main2Activity進入“已銷毀”狀态!");
    }
}
           

驗證結果:

  1. 正常進入Activity,log日志輸出:
    Android學習之詳解Activity的生命周期
  2. 點選Back鍵正常退出Activity,log日志輸出:
    Android學習之詳解Activity的生命周期
  3. 正常進入Activity,點選Home鍵傳回主界面,log日志輸出:
    Android學習之詳解Activity的生命周期
  4. 點完Home鍵,重新進入Activity,log日志輸出:
    Android學習之詳解Activity的生命周期
  5. 正常進入Activity,啟動另外一個Activity2,log日志輸出:
    Android學習之詳解Activity的生命周期
  6. 進入另外一個Activity2後,點選Back鍵再次回到Activity,log日志輸出:
    Android學習之詳解Activity的生命周期
  7. 正常進入Activity,進入分屏模式,且失去焦點時,log日志輸出:
    Android學習之詳解Activity的生命周期
  8. Activity退出分屏模式,擷取焦點進入全屏模式,log日志輸出:
    Android學習之詳解Activity的生命周期

結論:

當Activity啟動時,會依次調用

onCreate()

,

onStart()

,

onResume()

,也就是Activity已在前台可見,并具有使用者輸入焦點,可與使用者互動了,而當Activity退到背景時(不可見,點選Home或者被新的Activity完全覆寫),

onPause()

onStop()

會依次被調用。當Activity重新回到前台(從手機主螢幕回到原Activity或者被覆寫後又回到原Activity)時,

onRestart()

onStart()

onResume()

會依次被調用。當Activity退出&銷毀時(點選Back鍵),

onPause()

onStop()

onDestroy()

會依次被調用,到此Activity的整個生命周期方法回調完成。

參考文章:

Android開發者:Activity簡介 https://developer.android.google.cn/guide/components/activities/intro-activities

4.1.1 Activity初學乍練 https://www.runoob.com/w3cnote/android-tutorial-activity.html

Android之Activity生命周期淺析(一) https://blog.csdn.net/javazejian/article/details/51932554