KotlinでViewModelとPresenterとControllerをどうすれば楽にView層で使えるのか考察してみました。
ここでは架空のフレームワークを使っています。適宜利用するフレームワークに脳内変換してください。
Presenter->View
Clean Architectureでよくみる図のように、ViewはPresenterから発行される値をViewModelで監視します。
class ViewModel {
internal val mutableHogeFlow = MutableStateFlow("")
val hogeFlow: StateFlow<String>
get() = mutableHogeFlow
}
class Presenter(private val viewModel: ViewModel): UsecaseOutputPort {
override fun handle(hoge: String) {
viewModel.mutableHogeFlow.value = hoge
}
}
class View(private val viewModel): CoroutineScope {
val hoge = viewModel.hogeFlow.value
init() {
launch {
viewModel.hogeFlow.collect { hoge = it }
}
}
}
ViewModelではFlowを使ってView側に変更を通知できるようにします。
View->Controller
本題です。
入力用のViewModelを用意します。
ViewModelにon〇〇()のようなControllerの操作をするメソッドを持たせるのは責務違反なので、MVVMのようにViewModelに全てまとめるのではなく、Presenterで使うViewModelとControllerで使うViewModelは分けておくべきです。また、Controllerを操作する際は直接View側でViewModelの値をControllerで渡すべきです。
class ViewModel {
var hoge = ""
}
class Controller {
fun doSomething(hoge: String)
}
class View(val controller: Controller) {
val viewModel = ViewModel()
val button = Button(
onClick = { controller.doSomething(viewModel.hoge) }
)
val text = Text(
onChange = { viewModel.hoge = it }
)
}
まとめ
PresenterとController用のViewModelは分けましょう。