Android Activity 與 Fragment

在 Android 開發中,ActivityFragment 是建構使用者介面 (UI) 的基石。雖然現代 Android 開發(Modern Android Development (MAD))強調使用 Jetpack Compose 來建構 UI,但 Activity 作為應用程式的進入點與容器,依然扮演著不可或缺的角色。

Activity (活動)

Activity 是 Android 應用程式的單一螢幕,使用者可以與之互動。它是 Android 舊時代的四大元件 (Activity, Service, BroadcastReceiver, ContentProvider) 中最核心的一個。

角色與職責

在傳統的 Android 開發中 (View System),一個 App 通常由多個 Activity 組成 (Multi-Activity Architecture),例如 MainActivity, SettingsActivity, DetailActivity

但在現代架構中,我們推薦 Single Activity Architecture (單一 Activity 架構)

  • 整個 App 只有一個 MainActivity
  • 頁面的切換由 Navigation Component 搭配 FragmentsComposables 來完成。
  • Activity 主要負責當作「容器」,處理系統層級的互動(如權限請求、視窗設定)。

在過去,一個頁面通常就是一個 Activity。但在約 2023 年之後,單一 Activity 架構 (Single-Activity Architecture) 已成為標準。

  • 現況: 整個 App 通常只有一個 MainActivity,作為程式的入口點。
  • 演變: 所有的 UI 切換、導覽都交給了 Jetpack Compose 與 Navigation Component。你不再頻繁地建立新的 Activity,而是建立不同的 @Composable 函式。

註冊 Activity

每個 Activity 都必須在 AndroidManifest.xml 中宣告,否則系統無法啟動它並會拋出例外。

<manifest ...>
    <application ...>
        <activity android:name=".MainActivity" exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Activity Lifecycle (生命週期)

Activity 會在不同的狀態間轉換。了解生命週期對於管理資源(如暫停影片播放、釋放相機)至關重要。

  1. onCreate(): Activity 建立時呼叫。進行初始化佈局 (Set Content View)、變數綁定的地方。
  2. onStart(): Activity 即將對使用者可見。
  3. onResume(): Activity 位於前景且可與使用者互動。
  4. onPause(): Activity 正在失去焦點(例如跳出一個對話框,或使用者準備離開)。應在此處暫停耗電操作。
  5. onStop(): Activity 對使用者完全不可見。
  6. onDestroy(): Activity 被銷毀。
Configuration Changes (組態變更):當螢幕旋轉、語系切換或深色模式切換時,預設情況下 Activity 會被銷毀並重建 (Destroy -> Create)。這意味著變數會被重置。我們通常使用 ViewModelonSaveInstanceState 來保存狀態。

Fragment (片段)

Fragment 代表 Activity 使用者介面的一部分或一種行為。你可以把 Fragment 想像成一個「迷你 Activity」,它有自己的生命週期,但必須依附在 Activity 之下。

為什麼需要 Fragment?

  1. 模組化 UI:在大螢幕 (平板) 上,可以同時顯示多個 Fragment (左邊列表、右邊內容);在手機上則分頁顯示。
  2. 可重用性:同一個 Fragment 可以被不同的 Activity 重複使用。

Fragment Lifecycle

Fragment 的生命週期比 Activity 更複雜,因為它與 Activity 的狀態連動:

  1. onAttach(): Fragment 與 Activity 關聯。
  2. onCreate(): Fragment 建立。
  3. onCreateView(): 建立 Fragment 的 UI (Layout)。
  4. onViewCreated(): UI 建立完成。這是初始化 View 邏輯 (如設定 Click Listener) 最常用的地方。
  5. onDestroyView(): Fragment 的 UI 被移除。
  6. onDetach(): Fragment 與 Activity 解除關聯。

現代開發中的選擇

Jetpack Compose 與 Activity

如果你使用 Jetpack Compose,你不需要 Fragments。 Compose 的 Composable 函式可以直接取代 Fragment 的角色。

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            // 這裡就是你的 Compose App 入口,不需要 Fragment
            MyAppNavHost() 
        }
    }
}

這大大簡化了架構,因為 Composable 的生命週期比 Fragment 簡單得多。

在現代的 宣告式 UI (Declarative UI) 趨勢下,Fragment 的功能已經被 Composable 函式所取代。

  • 過去: 你需要 FragmentManager 來切換 Fragment,處理複雜的 onAttach, onCreateView, onDestroyView 等生命週期。
  • 現在: 你只需要透過 Compose Navigation 來切換不同的 @Composable。
    • 輕量化: Composable 只是函數,啟動速度比 Fragment 快得多,記憶體消耗也更低。
    • 生命週期: Compose 有自己的 CompositionLifecycle,比 Fragment 那惡名昭彰的複雜生命週期簡單許多。

傳統 View System

如果你維護的是舊專案,或者使用 XML 佈局,那 Fragment + Navigation Component 依然是標準作法。

Intent (意圖) - 元件間的溝通

Intent 是 Android 中用於在元件之間傳遞訊息的物件。

顯式 Intent (Explicit Intent)

明確指定要啟動哪個 Activity。

val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)

隱式 Intent (Implicit Intent)

不指定元件名稱,而是宣告「我想做什麼 (Action)」,讓系統找出適合的 App 來處理。例如:打開網頁、撥打電話。

val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.com"))
startActivity(intent)

小結

  • Activity 是 UI 的容器與進入點。
  • Fragment 是可重用的 UI 模組(在使用 Compose 時可被取代)。
  • Intent 用於連接不同的元件。
  • 掌握生命週期 (onCreate, onResume...) 對於開發穩定的 App 至關重要。