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

Activity

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

移動應用體驗與桌面體驗的不同之處在於,用戶與應用的互動並不總是在同一位置開始,而是經常以不確定的方式開始。例如,如果您從主屏幕打開電子郵件應用,可能會看到電子郵件列表,如果您通過社交媒體應用啓動電子郵件應用,則可能會直接進入電子郵件應用的郵件撰寫界面。
Activity類的目的就是促進這種範式的實現。當一個應用調用另一個應用時,調用方應用會調用另一個應用中的 Activity,而不是整個應用。通過這種方式,Activity 充當了應用與用戶互動的入口點。您可以將 Activity 實現爲Activity類的子類。
下面是關於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 生命週期的簡化圖:
activity_lifecycle
當用戶瀏覽、退出和返回到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()

備註:

AlertDialogPopWindow是不會觸發上述 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日誌輸出:
    在這裏插入圖片描述
  2. 點擊Back鍵正常退出Activity,log日誌輸出:
    在這裏插入圖片描述
  3. 正常進入Activity,點擊Home鍵返回主界面,log日誌輸出:
    在這裏插入圖片描述
  4. 點完Home鍵,重新進入Activity,log日誌輸出:
    在這裏插入圖片描述
  5. 正常進入Activity,啓動另外一個Activity2,log日誌輸出:
    在這裏插入圖片描述
  6. 進入另外一個Activity2後,點擊Back鍵再次回到Activity,log日誌輸出:
    在這裏插入圖片描述
  7. 正常進入Activity,進入分屏模式,且失去焦點時,log日誌輸出:
    在這裏插入圖片描述
  8. Activity退出分屏模式,獲取焦點進入全屏模式,log日誌輸出:
    在這裏插入圖片描述

結論:

當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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章