Android – ViewModel Provider 如何正確取得ViewModel?

發布日期:2024/11/22
瀏覽次數:41

在 Android 開發中,ViewModel 是 MVVM 架構中負責管理 UI 資料邏輯的組件,常透過不同的方式來取得 ViewModel。以下是三種取得方式的詳細說明及適合的使用場景:

activityViewModels()

用法

private val viewModel: MyViewModel by activityViewModels()

特性

是 Jetpack Navigation 或 Fragment KTX 提供的擴充函數。

取得的是與宿主 Activity 共享的 ViewModel。

當 Fragment 與 Activity 需要共享資料時非常實用。

ViewModel 的生命週期與 宿主 Activity 一致,當 Activity 被銷毀時,ViewModel 也會被清除。

適用情境

需要在多個 Fragment 中共享資料,並且資料的管理由宿主 Activity 負責。

例如:Fragment A 和 Fragment B 都需要共享用戶的輸入或應用程式的狀態。

viewModels()

用法

private val viewModel: MyViewModel by viewModels()

特性

取得的是與當前 Fragment(或 Activity)相關聯的 ViewModel。

ViewModel 的生命週期與 FragmentActivity 相同。

如果用在 Fragment 中,不會與其他 Fragment 或宿主 Activity 共享資料。

適用情境

當 ViewModel 只需要為單個 Fragment 或 Activity 提供邏輯與數據處理時使用。

例如:Fragment 單獨處理其自己的頁面邏輯(如表單驗證、API 請求等)。

ViewModelProvider(this)

用法

val viewModel = ViewModelProvider(this).get(MyViewModel::class.java)

特性

是 Jetpack 原始的 ViewModel 工廠方法。

必須明確指定 ViewModel 的類型,例如 MyViewModel::class.java。

當 this 是 Activity 時,ViewModel 與 Activity 同生命週期;當 this 是 Fragment 時,ViewModel 與 Fragment 同生命週期。

需要手動處理工廠(ViewModelProvider.Factory)來提供參數化的 ViewModel。

適用情境

舊版本的 Android 開發中,或者需要完全自訂 ViewModel 初始化邏輯時使用。

若無法使用 KTX 提供的擴充函數(如 viewModels() 或 activityViewModels()),此方法仍然是基礎選擇。

選擇使用的指導原則

1. 需要跨 Fragment 共享資料

使用 activityViewModels(),這樣可以保證所有 Fragment 與 Activity 共享相同的 ViewModel。

2. 單一 Fragment 或 Activity 使用

使用 viewModels(),這樣可以讓 ViewModel 僅與單一 Fragment 或 Activity 綁定。

3. 高度客製化或不支援擴充函數

使用 ViewModelProvider(this),尤其是在需要自訂初始化邏輯時。

其他補充

如果 ViewModel 需要特定的參數(例如 API token),通常需要實作自訂的 ViewModelProvider.Factory,而 viewModels() 和 activityViewModels() 都可以接受 factory 作為參數:

private val viewModel: MyViewModel by viewModels { MyViewModelFactory(token) }

Like