Examples
This section provides examples of how to implement the adidas MVI library in your Android application. For more detail check the sample provided.
1. Login Flow Example
Here is a complete example of how to implement a login flow using the adidas MVI library.
ViewModel Implementation
The following code shows the LoginViewModel
, which handles the login process.
class LoginViewModel(
logger: Logger,
coroutineDispatcher: CoroutineDispatcher = Dispatchers.Default
) : ViewModel(), MviHost<LoginIntent, State<LoginState, LoginSideEffect>> {
private val reducer = Reducer(
coroutineScope = viewModelScope,
defaultDispatcher = coroutineDispatcher,
initialInnerState = LoginState.LoggedOut(isLoggingIn = false),
logger = logger,
intentExecutor = this::executeIntent,
)
override val state = reducer.state
override fun execute(intent: LoginIntent) {
reducer.executeIntent(intent)
}
private fun executeIntent(intent: LoginIntent) =
when (intent) {
is LoginIntent.Login -> executeLogin(intent)
LoginIntent.Logout -> executeLogout()
LoginIntent.Close -> executeClose()
}
private fun executeLogin(intent: LoginIntent.Login) = flow {
emit(LoginTransform.SetIsLoggingIn(isLoggingIn = true))
delay(300) // Simulate a network call
emit(LoginTransform.SetIsLoggingIn(isLoggingIn = false))
if (intent.username.isEmpty() || intent.password.isEmpty()) {
emit(LoginTransform.AddSideEffect(LoginSideEffect.ShowInvalidCredentialsError))
} else {
emit(LoginTransform.SetLoggedIn(intent.username))
}
}
}
Intent Example
Define the intents that your application will handle:
internal sealed class LoginIntent : Intent {
data class Login(val username: String, val password: String) : LoginIntent()
object Logout : LoginIntent()
object Close : LoginIntent()
}
Activity Implementation
Here's how to set up the MviSampleActivity
to use the LoginViewModel
.
class MviSampleActivity : AppCompatActivity() {
private val viewModel: LoginViewModel by viewModel() // Assuming you're using Koin for dependency injection
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
LoginScreen(viewModel)
}
}
}
View Implementation
In your composable function, observe the state from the LoginViewModel
and render the UI accordingly.
@Composable
fun LoginScreen(viewModel: LoginViewModel) {
val state by viewModel.state.collectAsState()
when (state) {
is LoginState.LoggedOut -> {
// Show login UI
}
is LoginState.LoggedIn -> {
// Show logged-in UI
}
}
}