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
}
0 件のコメント:
コメントを投稿