都能看的懂的 Activity 概述和生命週期詳解(Android進階開發)

Activity 基本

目錄

  • 概述
  • 創建Activity
  • Activity的生命週期概述
  • Activity的生命週期詳解

一、概述

  • 應用場景:Activity 是一個應用組件,用戶可與其提供的屏幕進行交互,以執行撥打電話、拍攝照片、發送電子郵件或查看地圖等操作。 每個 Activity 都會獲得一個用於繪製其用戶界面的窗口。窗口通常會充滿屏幕,但也可小於屏幕並浮動在其他窗口之上。
  • 堆棧機制:一個應用通常由多個彼此鬆散聯繫的 Activity 組成。 一般會指定應用中的某個 Activity 爲“主”Activity,即首次啓動應用時呈現給用戶的那個 Activity。 而且每個 Activity 均可啓動另一個 Activity,以便執行不同的操作。 每次新 Activity 啓動時,前一 Activity 便會停止,但系統會在堆棧(“返回棧”)中保留該 Activity。 當新 Activity 啓動時,系統會將其推送到返回棧上,並取得用戶焦點。 返回棧遵循基本的“後進先出”堆棧機制,因此,當用戶完成當前 Activity 並按“返回”按鈕時,系統會從堆棧中將其彈出(並銷燬),然後恢復前一 Activity。 (任務和返回棧文檔中對返回棧有更詳細的闡述。)
  • 回調機制:當一個 Activity 因某個新 Activity 啓動而停止時,系統會通過該 Activity 的生命週期回調方法通知其這一狀態變化。Activity 因狀態變化—系統是創建 Activity、停止 Activity、恢復 Activity 還是銷燬 Activity— 而收到的回調方法可能有若干種,每一種回調都會爲您提供執行與該狀態變化相應的特定操作的機會。 例如,停止時,您的 Activity 應釋放任何大型對象,例如網絡或數據庫連接。 當 Activity 恢復時,您可以重新獲取所需資源,並恢復執行中斷的操作。 這些狀態轉變都是 Activity 生命週期的一部分。

二、創建Activity

  1. 創建佈局文件

這個沒什麼好說的,下面就是一個最普通的佈局了。

    //activity_one.xml 創建
    <LinearLayout xmlns:android#"http://schemas.android.com/apk/res/android"
      android:id#"@+id/linearLayout"
      android:layout_width#"match_parent"
      android:layout_height#"match_parent"
      android:gravity#"center"
      android:orientation#"vertical">
          <TextView
              android:id#"@+id/textView"
              android:layout_width#"wrap_content"
              android:layout_height#"wrap_content"
              android:layout_margin#"2px"
              android:text#"文本框"
            />
    </LinearLayout>
  1. 創建Activity的類

onCreate() 您必須實現此方法。系統會在創建您的 Activity 時調用此方法。您應該在實現內初始化 Activity
的必需組件。 最重要的是,您必須在此方法內調用setContentView(),以定義 Activity 用戶界面的佈局。

    //創建你的Activity類需要繼承自Activity或者其子類
    public class MyActivity1 extends AppCompatActivity {

      @Override//一個Activity中必須要實現onCreate方法
      protected void onCreate(Bundle savedInstanceState) {
        //這個方法是必須要寫的
        super.onCreate(savedInstanceState);
        //這裏需要指定你的佈局文件activity_one.xml
        setContentView(R.layout.activity_one);
      }
    }
  1. 在AndroidManifest.xml中聲明Activity

AndroidManifest.xml也就是我們當前模塊的清單文件,只有在清單文件中聲明您的
Activity,這樣系統才能知道有這麼一個Activity的存在,纔可以訪問這個Activity。

      <!--這裏設置過濾器,將這個Activity設置爲你的程序入口-->
      <intent-filter>
        <action android:name#"android.intent.action.MAIN" />

        <category android:name#"android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
  1. 啓動調試,這裏就不演示了,只要啓動你的模擬器即可

三、Activity的生命週期概述

  1. 我們先上代碼和圖片,讓大家看看Activity的一生到底是怎麼樣的

關於圖中需要實現說明幾個關鍵詞

1.entire lifetime:表示一個最簡單的完整的Activity生命週期會按照如下順序回調:onCreate -> onStart > onResume -> onPause -> onStop -> onDestroy。

在這裏插入圖片描述

2.visible lifetime:當執行onStart回調方法時,Activity開始被用戶所見(也就是說,onCreate時用戶是看不到此Activity的,那用戶看到的是哪個?當然是此Activity之前的那個Activity),一直到onStop之前,此階段Activity都是被用戶可見,稱之爲visible lifetime。

在這裏插入圖片描述

3.foreground lifetime:當執行到onResume回調方法時,Activity可以響應用戶交互,一直到onPause方法之前,此階段Activity稱之爲foreground lifetime。

在這裏插入圖片描述

public class MyActivity1 extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_one);
    // 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.
  }
}
  1. 我們來舉幾個實際的例子,讓大家更能生動的理解Activity的生命週期
  • 下面我們直接展示具體例子:我們假設現在有兩個Activity,別是A和B,然後現在Activity A上有一個按鈕可以跳轉到Activity B,我們就以這個場景來按照順序做演示。

  • 1.已經啓動了Activity A,現在點擊A中的按鈕,跳轉到Activity B中,這時候我們看看兩個Activity的生命週期是怎麼樣的。

回調順序:onPause -> B:onCreate -> B:onStart -> B:onResume -> A:onStop。

在這裏插入圖片描述

  • 2.這時候B正在工作運轉,然後我們點擊手機自帶的Back返回鍵,來看看這個生命週期的運轉

回調順序:B:onPause -> A:onRestart -> A:onStart -> A:onResume -> B:onStop
-> B:onDestroy。

在這裏插入圖片描述

  • 3.這時候B已經被銷燬了,我們在A的界面上,然後我們嘗試短暫按下手機的Home鍵

回調順序:A:onPause -> A:onStop。

在這裏插入圖片描述

  • 我們可以清楚的看到我們平時對Activity的操作中Activity生命週期運轉的不同情況,也就是可以大致總結
  • 1.Activity之間的跳轉會將前一個Activity壓入堆棧
  • 2.Back鍵的跳轉會銷燬當前Activity
  • 3.Home鍵的跳轉會不會銷燬當前Activity

四、Activity的生命週期詳解

  1. 首先我們直接上一張表來看看Activity生命週期更加詳細的信息
    在這裏插入圖片描述
  2. 接着我們來說說管理Activity生命週期的幾個技巧
  • 技巧一:使用 onPause()向存儲設備寫入至關重要的持久性數據(例如用戶編輯)。

(onPause()、onStop() 和 onDestroy())。由於 onPause() 是這三個方法中的第一個,因此Activity 創建後,onPause() 必定成爲最後調用的方法,然後才能終止進程 — 如果系統在緊急情況下必須恢復內存,則可能不會調用onStop() 和 onDestroy()。因此,您應該使用 onPause() 向存儲設備寫入至關重要的持久性數據(例如用戶編輯)。不過,您應該對 onPause()調用期間必須保留的信息有所選擇,因爲該方法中的任何阻止過程都會妨礙向下一個 Activity 的轉變並拖慢用戶體驗。

  • 技巧二:通過onSaveInstanceState()方法來更好的保護Activity的狀態數據,防止特殊情況下重要數據的丟失(如系統因爲內存不足強行銷燬Activity)

當 Activity 暫停或停止時,Activity 的狀態會得到保留。 確實如此,因爲當 Activity 暫停或停止時,Activity 對象仍保留在內存中 — 有關其成員和當前狀態的所有信息仍處於活動狀態。 因此,用戶在 Activity 內所做的任何更改都會得到保留,這樣一來,當 Activity 返回前臺(當它“繼續”)時,這些更改仍然存在。

不過,當系統爲了恢復內存而銷燬某項 Activity 時,Activity 對象也會被銷燬,因此係統在繼續 Activity 時根本無法讓其狀態保持完好,而是必須在用戶返回 Activity 時重建 Activity 對象。但用戶並不知道系統銷燬 Activity 後又對其進行了重建,因此他們很可能認爲 Activity 狀態毫無變化。 在這種情況下,您可以實現另一個回調方法對有關 Activity 狀態的信息進行保存,以確保有關 Activity 狀態的重要信息得到保留:onSaveInstanceState()。

系統會先調用 onSaveInstanceState(),然後再使 Activity 變得易於銷燬。系統會向該方法傳遞一個 Bundle,您可以在其中使用 putString() 和putInt() 等方法以名稱-值對形式保存有關 Activity 狀態的信息。然後,如果系統終止您的應用進程,並且用戶返回您的 Activity,則系統會重建該 Activity,並將 Bundle 同時傳遞給 onCreate() 和 onRestoreInstanceState()。您可以使用上述任一方法從 Bundle 提取您保存的狀態並恢復該 Activity 狀態。如果沒有狀態信息需要恢復,則傳遞給您的 Bundle 是空值(如果是首次創建該 Activity,就會出現這種情況)。

  1. 處理配置變更(例如手機旋轉)
  • 說明:有些設備配置可能會在運行時發生變化(例如屏幕方向、鍵盤可用性及語言)。 發生此類變化時,Android 會重建運行中的 Activity(系統調用onDestroy(),然後立即調用 onCreate())。此行爲旨在通過利用您提供的備用資源(例如適用於不同屏幕方向和屏幕尺寸的不同佈局)自動重新加載您的應用來幫助它適應新配置。

  • 正如上文所述,處理此類重啓的最佳方法是利用onSaveInstanceState() 和 onRestoreInstanceState()(或 onCreate())保存並恢復 Activity 的狀態。

  • 接下來我通過一段代碼來展示如何通過onSaveInstanceState() 來實現狀態的保存

import android.app.Activity;
import android.os.PersistableBundle;
import android.util.Log;
import android.view.View;
import android.view.ViewStub;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

public class MyActivity1 extends Activity {

  private static final String TAG = "Activity";

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_one);
    //方式一:通過onCreate來獲取之前的狀態信息
    // 這裏需要檢查是否正在重新創建一個以前銷燬的實例
    if (savedInstanceState != null) {
      // 從已保存狀態恢復成員的值
      String string = savedInstanceState.getString(TAG);
      Log.i(TAG, "通過onCreate獲取屏幕旋轉之前狀態"+string);
    }
  }

  @Override
  public void onSaveInstanceState(Bundle savedInstanceState) {
    // 保存用戶自定義的狀態
    savedInstanceState.putString(TAG, "hello");
    // 調用父類交給系統處理,這樣系統能保存視圖層次結構狀態
    super.onSaveInstanceState(savedInstanceState);
  }

  //方式二:onRestoreInstanceState()來獲取之前的狀態信息
  //系統onRestoreInstanceState()只有在存在保存狀態的情況下才會恢復,因此您不需要檢查是否Bundle爲空
  public void onRestoreInstanceState(Bundle savedInstanceState) {
    // 總是調用超類,以便它可以恢復視圖層次超級
    super.onRestoreInstanceState(savedInstanceState);
    // 從已保存的實例中恢復狀態成員
    String string = savedInstanceState.getString(TAG);
    Log.i(TAG, "通過onRestoreInstanceState獲取屏幕旋轉之前狀態:"+string);
  }
}

在這裏插入圖片描述
在這裏插入圖片描述

這裏着重說明一下一些注意點

1、如果是用戶自動按下返回鍵,或程序調用finish()退出程序,是不會觸發onSaveInstanceState()和onRestoreInstanceState()的。
2、每次用戶旋轉屏幕時,您的Activity將被破壞並重新創建。當屏幕改變方向時,系統會破壞並重新創建前臺Activity,因爲屏幕配置已更改,您的Activity可能需要加載替代資源(例如佈局)。即會執行onSaveInstanceState()和onRestoreInstanceState()的。

  1. 協調 Activity之間的切換

當一個 Activity 啓動另一個 Activity 時,它們都會體驗到生命週期轉變。第一個 Activity 暫停並停止(但如果它在後臺仍然可見,則不會停止)時,同時系統會創建另一個 Activity。 如果這些 Activity 共用保存到磁盤或其他地方的數據,必須瞭解的是,在創建第二個 Activity 前,第一個 Activity 不會完全停止。更確切地說,啓動第二個 Activity 的過程與停止第一個 Activity 的過程存在重疊。

生命週期回調的順序經過明確定義,當兩個 Activity 位於同一進程,並且由一個 Activity 啓動另一個 Activity 時,其定義尤其明確。 以下是當 Activity A 啓動 Activity B 時一系列操作的發生順序:

Activity A 的 onPause() 方法執行。
Activity B 的 onCreate()、onStart() 和 onResume() 方法依次執行。(Activity B 現在具有用戶焦點。)
然後,如果 Activity A 在屏幕上不再可見,則其 onStop() 方法執行。
您可以利用這種可預測的生命週期回調順序管理從一個 Activity 到另一個 Activity 的信息轉變。 例如,如果您必須在第一個 Activity 停止時向數據庫寫入數據,以便下一個 Activity 能夠讀取該數據,則應在 onPause() 而不是 onStop() 執行期間向數據庫寫入數據。

在這裏插入圖片描述

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