ViewModel 總覽 (Views)
ViewModel 類別是商業邏輯或畫面層級的狀態容器。這會向 UI 公開狀態,並封裝相關的商業邏輯。其主要優點在於可快取狀態,並透過設定變更保留。因此,在活動之間導覽或執行設定變更 (例如旋轉畫面) 時,UI 不必再次擷取資料。
ViewModel 優點
ViewModel 的替代方案為純類別,可保留 UI 中顯示的資料。在活動或 Navigation 到達網頁之間導覽時,可能會發生問題。如未使用儲存執行個體狀態機制來儲存資料,則系統會將其刪除。ViewModel 提供能持續保留資料的便捷 API,可以解決此問題。
ViewModel 類別有兩項主要優點:
- 可讓您保留 UI 狀態。
- 提供商業邏輯存取。
範圍
將 ViewModel 執行個體化時,必須傳遞一個實作 ViewModelStoreOwner 介面的物件。這可以是 Navigation 目的地、Navigation 圖表、活動、片段,或實作介面的任何其他類型。ViewModel 的範圍則會限定於 ViewModelStoreOwner 的 Lifecycle 內。因此會保留在記憶體中,直到其 ViewModelStoreOwner 永久消失。
各種類別包括 ViewModelStoreOwner 介面的直接或間接子類別。直接子類別為 ComponentActivity、Fragment 和 NavBackStackEntry。如需間接子類別的完整清單,請參閱 ViewModelStoreOwner 參考資料。
實作 ViewModel
以下是使用者擲骰子畫面的 ViewModel 實作範例。
Kotlin
data class DiceUiState(
val firstDieValue: Int? = null,
val secondDieValue: Int? = null,
val numberOfRolls: Int = 0,
)
class DiceRollViewModel : ViewModel() {
// Expose screen UI state
private val _uiState = MutableStateFlow(DiceUiState())
val uiState: StateFlow<DiceUiState> = _uiState.asStateFlow()
// Handle business logic
fun rollDice() {
_uiState.update { currentState ->
currentState.copy(
firstDieValue = Random.nextInt(from = 1, until = 7),
secondDieValue = Random.nextInt(from = 1, until = 7),
numberOfRolls = currentState.numberOfRolls + 1,
)
}
}
}
Java
public class DiceUiState {
private final Integer firstDieValue;
private final Integer secondDieValue;
private final int numberOfRolls;
// ...
}
public class DiceRollViewModel extends ViewModel {
private final MutableLiveData<DiceUiState> uiState =
new MutableLiveData(new DiceUiState(null, null, 0));
public LiveData<DiceUiState> getUiState() {
return uiState;
}
public void rollDice() {
Random random = new Random();
uiState.setValue(
new DiceUiState(
random.nextInt(7) + 1,
random.nextInt(7) + 1,
uiState.getValue().getNumberOfRolls() + 1
)
);
}
}
接著,您可以從活動中存取 ViewModel,如以下程式碼片段所示:
Kotlin
import androidx.activity.viewModels
class DiceRollActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Create a ViewModel the first time the system calls an activity's onCreate() method.
// Re-created activities receive the same DiceRollViewModel instance created by the first activity.
// Use the 'by viewModels()' Kotlin property delegate
// from the activity-ktx artifact
val viewModel: DiceRollViewModel by viewModels()
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect {
// Update UI elements
}
}
}
}
}
Java
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create a ViewModel the first time the system calls an activity's onCreate() method.
// Re-created activities receive the same MyViewModel instance created by the first activity.
DiceRollViewModel model = new ViewModelProvider(this).get(DiceRollViewModel.class);
model.getUiState().observe(this, uiState -> {
// update UI
});
}
}
為您推薦
- 注意:系統會在 JavaScript 關閉時顯示連結文字
- 搭配生命週期感知元件使用 Kotlin 協同程式
- 儲存 UI 狀態
- 載入並顯示分頁資料