Interfaces are useful in case of faking in previews.
For example:
interface ItemViewModel {
val title: CMutableStateFlow<String>
val isEditing: CStateFlow<Boolean>
val canSave: CStateFlow<Boolean>
}
class ItemViewModelImpl(
private val heavyDependency1: HeavyDependency1,
private val heavyDependency2: HeavyDependency2,
...
private val heavyDependency101: HeavyDependency101,
): ViewModel(), ItemViewModel {
override val title = MutableStateFlow("").cMutableStateFlow()
override val isEditing = MutableStateFlow(false).cMutableStateFlow()
override val canSave = MutableStateFlow(false).cMutableStateFlow()
}
class ItemViewModelFake(
title: String,
isEditing: Boolean = false,
canSave: Boolean = false,
): ViewModel(), ItemViewModel {
override val title = MutableStateFlow(title).cMutableStateFlow()
override val isEditing = MutableStateFlow(isEditing).cStateFlow()
override val canSave = MutableStateFlow(canSave).cStateFlow()
}
@Composable
fun Item(viewModel: ViewModel /*for the sake of simplicity without DI*/) {
// some UI
}
And use them for previews:
@Preview
@Composable
private fun ItemPreview() {
MaterialTheme {
Item(
ViewModelFake(title = "123")
)
}
}
@Preview
@Composable
private fun ItemEditingCannotSavePreview() {
MaterialTheme {
Item(
ViewModelFake(title = "123", isEditing = true)
)
}
}
@Preview
@Composable
private fun ItemEditingCanSavePreview() {
MaterialTheme {
Item(
ViewModelFake(title = "123", isEditing = true, canSave = true)
)
}
}
But not for SwiftUI. We can't make extensions for protocols (to be ObservableObject).
Interfaces are useful in case of faking in previews.
For example:
And use them for previews:
But not for SwiftUI. We can't make extensions for protocols (to be ObservableObject).