Andoroid MVI Example: Difference between revisions
Line 16: | Line 16: | ||
And for Ktor | And for Ktor | ||
<syntaxhighlight lang="kts"> | <syntaxhighlight lang="kts"> | ||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0") | |||
implementation ('io.ktor:ktor-client-serialization:<latest-version>') | |||
implementation("io.ktor:ktor-client-core:<latest-version>") | |||
implementation("io.ktor:ktor-client-content-negotiation:<latest-version>") | |||
implementation("io.ktor:ktor-client-android:<latest-version>") | |||
runtimeOnly("io.ktor:ktor-serialization-kotlinx-json:<latest-version>") | runtimeOnly("io.ktor:ktor-serialization-kotlinx-json:<latest-version>") | ||
</syntaxhighlight> | |||
=Resource= | |||
This is a class which is called in our case DataState but lots of people call this Resource. In this class we create a function for each state we are managing and the data we need to create this State. | |||
<syntaxhighlight lang="kotlin"> | |||
package nz.co.bibble.mviexample | |||
sealed class DataState<T> { | |||
data class Loading<T>(val isLoading: Boolean) : DataState<T>() | |||
data class Success<T>(val data: T) : DataState<T>() | |||
data class Error<T>(val uiComponent: UIComponent) : DataState<T>() | |||
} | |||
sealed class UIComponent { | |||
data class Total(val text: String) : UIComponent(), | |||
} | |||
</syntaxhighlight> | |||
=Post API= | |||
This not part of MVI, it is a service used for the data. Previously I have used Retrofit to do this job and it would live in the Data Layer. Here we create an interface which would normally be in the Domain Layer | |||
<syntaxhighlight lang="kotlin"> | |||
interface PostApi { | |||
suspend fun getPosts(): List<Post> | |||
} | |||
</syntaxhighlight> | |||
And the implementation | |||
<syntaxhighlight lang="kotlin"> | |||
class PostApiImpl( | |||
private val httpClient :HttpClient | |||
):PostApi { | |||
override suspend fun getPosts(): List<Post> { | |||
return httpClient.get( | |||
"https://jsonplaceholder.typicode.com/posts" | |||
).body() | |||
} | |||
} | |||
</syntaxhighlight> | </syntaxhighlight> |
Revision as of 01:09, 8 March 2025
Introduction
Wanted to revisit the MVI pattern to just have another look using another approach this example uses ktor, an asyncronous client, where I was previously using Retrofit, and Oribit MVI which provides the container and the Store elements. (See Below)
The Pattern
Last time I looked at this we had this diagram
For this example I will be using this one
Setup
Like this, as I never knew you could do this to get the latest version, don't do it at work but safe for home I guess. For Orbit MVI we add
implementation("org.orbit-mvi:orbit-core:<latest-version>")
implementation("org.orbit-mvi:orbit-viewmodel:<latest-version>")
implementation("org.orbit-mvi:orbit-compose:<latest-version>")
testImplementation("org.orbit-mvi:orbit-test:<latest-version>")
And for Ktor
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0")
implementation ('io.ktor:ktor-client-serialization:<latest-version>')
implementation("io.ktor:ktor-client-core:<latest-version>")
implementation("io.ktor:ktor-client-content-negotiation:<latest-version>")
implementation("io.ktor:ktor-client-android:<latest-version>")
runtimeOnly("io.ktor:ktor-serialization-kotlinx-json:<latest-version>")
Resource
This is a class which is called in our case DataState but lots of people call this Resource. In this class we create a function for each state we are managing and the data we need to create this State.
package nz.co.bibble.mviexample
sealed class DataState<T> {
data class Loading<T>(val isLoading: Boolean) : DataState<T>()
data class Success<T>(val data: T) : DataState<T>()
data class Error<T>(val uiComponent: UIComponent) : DataState<T>()
}
sealed class UIComponent {
data class Total(val text: String) : UIComponent(),
}
Post API
This not part of MVI, it is a service used for the data. Previously I have used Retrofit to do this job and it would live in the Data Layer. Here we create an interface which would normally be in the Domain Layer
interface PostApi {
suspend fun getPosts(): List<Post>
}
And the implementation
class PostApiImpl(
private val httpClient :HttpClient
):PostApi {
override suspend fun getPosts(): List<Post> {
return httpClient.get(
"https://jsonplaceholder.typicode.com/posts"
).body()
}
}