MVVM with Flows in Kotlin
This story describes creating a simple Android application that uses MVVM architecture along with Flows .
Basics of Flow:
What is Flow ?
- A flow is a stream of values that are asynchronously computed.
- Flows emits values and there is other process/coroutines that receives/process the emitted values.
Creating Flows
Ways to Create Flow:
(1) Generate values by emitting each value
fun emitNumbers(): Flow<Int> = flow{
val numList = listOf<Int>(1,2,3,4,5,6,7)
numList.forEach {
delay(it*100L)
emit(it)
}
}
(2)A collection can be directly converted into a flow.
fun convertingCollectionInToFlow() = listOf<Int>(1,2,3,4,5,6,7,8,9,10).asFlow()
(3)A flow can be generated from a number of parameters of any type.
fun creatingFlowWithNumberOfParameters()= flowOf("one","two","three")
Using Flows in Android with MVVM Architecture:
The example explained in this story is a very basic example.
What this example does?
This example fetch list of data from network and displays in the list.
Architecture
Model:
Created a data class that represents the model of the API response
class PostsModel : ArrayList<PostsModel.PostsModelItem>(){
data class PostsModelItem(
val body: String, // cupiditate quo est a modi nesciunt soluta ipsa voluptas error itaque dicta in autem qui minus magnam et distinctio eum accusamus ratione error aut
val id: Int, // 100
val title: String, // at nam consequatur ea labore ea harum
val userId: Int // 10
)
}
API service Interface:
This interface contains the retrofit methods to fetch data from network
interface PostsService {
@GET("/posts")
suspend fun fetchPosts(): List<PostsModel.PostsModelItem>
}
Repository :
We need a repository to communicate with PostsService to fetch data.
This is the place where we use flow .
fun getPosts(): Flow<PostsModel.PostsModelItem>{
return flow {
val postList = postsService.fetchPosts()
println("PostsList is $postList")
postList.forEach {
emit(it)
delay(NEWS_DELAY)
}
}
}
Explanation:
The getPosts() method returns flow of model item.
This method calls a method from postsService and emit each item in the list to the viewModel with some delay.
ViewModel:
View model will have one method that returns live data. A flow can be converted to live data using method .asLiveData()
class ListViewModel: ViewModel() {
val posts = PostRepository().getPosts().asLiveData()
}
The received live data from view model will be observed in view as below:
View:
private fun observeViewModel() {
viewModel.posts.observe(this, Observer { post ->
loading_view.visibility = View.GONE
newsList.visibility = View.VISIBLE
newsListAdapter.onAddPostsItem(post)
newsList.smoothScrollToPosition(0)
})
}
Each item emitted from flow will be added to the top of the list and position is scrolled to the added position as above.
Github link for Code: