-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #37 from adidas/feature/add_docs_to_docusaurus
added formal docs to docusaurus and cleaned up
- Loading branch information
Showing
25 changed files
with
238 additions
and
662 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Binary file not shown.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
--- | ||
title: 2. Core Concepts | ||
sidebar_position: 2 | ||
--- | ||
|
||
# Core Concepts | ||
|
||
The **Model-View-Intent (MVI)** pattern in adidas MVI follows these principles: | ||
|
||
## Model | ||
|
||
The **Model** represents the state of the application. It’s immutable and stores all the information required to render the user interface. | ||
|
||
```kotlin | ||
sealed class LoginState { | ||
data class LoggedOut(val isLoggingIn: Boolean) : LoginState() | ||
data class LoggedIn(val username: String) : LoginState() | ||
} | ||
``` | ||
|
||
## View | ||
|
||
The **View** observes the model and updates itself accordingly. It reacts to changes in the **Model** and displays the current state. | ||
|
||
## Intent | ||
|
||
An **Intent** represents a user action or an event that leads to a state change in the **Model**. | ||
|
||
```kotlin | ||
sealed class LoginIntent { | ||
data class Login(val username: String, val password: String) : LoginIntent() | ||
object Logout : LoginIntent() | ||
} | ||
``` | ||
|
||
## Side Effects | ||
|
||
A **SideEffect** represents an external action triggered by a state change, such as network calls, database updates, or other asynchronous operations. | ||
|
||
```kotlin | ||
sealed class LoginSideEffect { | ||
object ShowInvalidCredentialsError : LoginSideEffect() | ||
object Close : LoginSideEffect() | ||
} | ||
``` | ||
|
||
## State | ||
|
||
The **State** combines the **ViewState** and **SideEffect** components to provide a unified application state. It helps manage complex states within the app. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
--- | ||
title: 4. Examples | ||
sidebar_position: 4 | ||
--- | ||
|
||
# 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. | ||
|
||
```kotlin | ||
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: | ||
|
||
```kotlin | ||
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`. | ||
|
||
```kotlin | ||
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. | ||
|
||
```kotlin | ||
@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 | ||
} | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
--- | ||
title: 3. Getting started | ||
sidebar_position: 3 | ||
--- | ||
|
||
# Getting Started | ||
|
||
To begin using adidas MVI in your project, follow these steps: | ||
|
||
## 1. Add the Dependency | ||
|
||
Add the following to your `build.gradle` file: | ||
|
||
```gradle | ||
implementation("com.adidas.mvi:mvi:{LATEST_VERSION}") | ||
``` | ||
|
||
Sync your project to download the necessary dependencies. | ||
|
||
## 2. Create the Components | ||
|
||
Here's an example of setting up the **LoginViewModel** and managing intents. | ||
|
||
### Login ViewModel | ||
|
||
The **LoginViewModel** manages user actions and updates the application state based on intents. | ||
|
||
```kotlin | ||
class LoginViewModel( logger: Logger ) : ViewModel(), MviHost<LoginIntent, State<LoginState, LoginSideEffect>> { | ||
private val reducer = Reducer( | ||
coroutineScope = viewModelScope, | ||
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() | ||
} | ||
} | ||
``` | ||
|
||
## 3. Update the Activity | ||
|
||
In your `Activity`, use the view model and set the content: | ||
|
||
```kotlin | ||
class MviSampleActivity : AppCompatActivity() { | ||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
setContent { | ||
LoginScreen() | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Now you're ready to use adidas MVI in your project! |
Oops, something went wrong.