ViewModel の概要(ビュー)
ViewModel クラスは、ビジネス ロジックまたは画面レベルの状態
ホルダーです。状態を UI に公開し、関連するビジネス ロジックをカプセル化します。状態がキャッシュに保存され、構成が変更されてもそれが維持されることが主なメリットです。つまり、アクティビティ間を移動するときや、画面の回転などの構成の変更に従うときに、UI
でデータを再度取得する必要がありません。
ViewModel のメリット
ViewModel の代わりに、UI に表示するデータを保持するプレーンクラスを利用できます。これは、アクティビティ間や Navigation デスティネーション間を移動する際に問題になることがあります。インスタンス状態保存メカニズムを使用して保存せずにこれを行うと、そのデータが破棄されます。ViewModel であれば、データの永続性のための便利な API を利用して、この問題を解決できます。
ViewModel クラスの主なメリットは基本的に次の 2 つです。
- UI 状態を保持できます。
- ビジネス ロジックにアクセスできます。
範囲
ViewModel をインスタンス化する場合、ViewModelStoreOwner インターフェースを実装するオブジェクトを渡します。これは、Navigation デスティネーション、Navigation
グラフ、アクティビティ、フラグメント、その他のインターフェースを実装するなんらかのタイプになります。これにより、ViewModel のスコープがLifecycleの
ViewModelStoreOwnerに設定されます。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 の状態を保存する
- ページング データを読み込む、表示する