🌄
[Android] ViewModelに依存したComposeのPreviewを表示する
やりたかったこと
ComposeのPreviewにAPIレスポンスのモックを表示したかった。
画像のLoginをタップ後APIから token が返却され、下部にあるtoken=
以降に値を表示するのをPreviewで再現したかった。
※tokenを表示するのはエンジニアとしてどうなのかというのはある
実装
Screen
@Composable
fun LoginScreen(viewModel: LoginViewModel) {
val scope = rememberCoroutineScope()
val state = viewModel.state.collectAsState() // Flow
Column {
...
// Text Fieldの実装
...
Button(onClick = {
scope.launch {
viewModel.login(email, password)
}.invokeOnCompletion {
....
}
}) {
Text(text = "Login")
}
Text(text = "token = ${state.value.token}") // ここをモックで表示したい
}
ViewModel
abstruct class
にViewModel()
を Implement しておき、「実際にStateを管理するクラス」と「Preview表示用のモッククラス」それぞれを作成し、共通部分(今回は state
)を使いまわすことで解決した。
abstruct class LoginViewModel : ViewModel() {
sealed class State {
data class Login(val token: String) : State()
}
abstract val state: MutableStateFlow<State>
}
@HiltViewModel
class LoginViewModelImpl @Inject constructor(
private val loginUseCase: LoginUseCase
) : LoginViewModel() {
private val _state = MutableStateFlow<State>(State.Login("")
override val state: MutableStateFlow<State>
get() = _state
suspend fun login(email: String, password: String) {
loginUseCase.login(email, password)
...
.onEach { response ->
_state.value = UiState.Login(response.token)
}
...
}
}
// Previewに表示するためのモッククラス
class FakeLoginViewModel : LoginViewModel() {
override val state: MutableStateFlow<State>
get() = MutableStateFlow(
State.Login("Fake Success! UseCase will return login token.")
)
}
Preview
@Preview
@Composable
fun PreviewLogin() {
LoginScreen(viewModel = FakeLoginViewModel())
}
Previewの表示結果
FakeLoginViewModel
で記述したテキストがPreviewに表示されている!
補足
今回は abstruct class
で実装しましたが、場合によっては interface
でも良いと思います。
Discussion