(本当は Compose のコード例(State/MutableState)にしたかったんだけど、まだ Jetpack Compose は Kotlin 1.5 に対応してないので sealed interface 使えないんだよね...)
ViewModel で持ってる LiveData を Activity で observe してるとする。
mutableValue に private は MainViewModel から見えなくなるのでダメ。
ということで sealed interface を使います。
ViewModel で持ってる LiveData を Activity で observe してるとする。
class MainActivity : AppCompatActivity() { private val viewModel: MainViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) viewModel.state.observe(this) { when (it) { is State.Data -> { println(it.value) } State.Loading -> { } } } } }
class MainViewModel : ViewModel() { private val _state = MutableLiveData<State>() val state: LiveData<State> get() = _state fun doSomething() { val state = _state.value if (state is State.Data) { state.mutableValue = Random.nextInt() } } } sealed class State { object Loading : State() data class Data(val id: String) : State() { // 変更できるのは MainViewModel からだけにしたいが、 // private にすると MainViewModel からも見えなくなる var mutableValue: Int = -1 val value: Int get() = mutableValue } }
↑ State.Data が持つ mutableValue は MainViewModel からのみ変更できるようにしたい。 mutableValue に private は MainViewModel から見えなくなるのでダメ。
private var mutableValue: Int = -1
これもダメ。 private sealed class State {
private data class Data(val id: String) : State() {
Data を top level にすると private をつけても MainViewModel から見えるけど、MainActivity から見えなくなるのでダメ。 sealed class State object Loading : State() // MainViewModel から mutableValue は見えるが // Data が MainActivity からは見えなくなる private data class Data(val id: String) : State() { var mutableValue: Int = -1 val value: Int get() = mutableValue }
ということで sealed interface を使います。
class MainViewModel : ViewModel() { private val _state = MutableLiveData<State>() val state: LiveData<State> get() = _state fun doSomething() { val state = _state.value if (state is DataImpl) { state.mutableValue = Random.nextInt() } } } sealed interface State object Loading : State sealed interface Data : State { val value: Int } private class DataImpl(val id: Int) : Data { // private class なので変更できるのは同じファイルからだけ var mutableValue: Int = id override val value: Int get() = mutableValue }