Loading...
Home
  • Tech Blogs
  • Videos
  • Conferences
    • Droidcon News
    • Upcoming Conferences
    • Become a Partner
    • Past Events
    • Keep Me Informed
    • Diversity Scholarships
  • Community
    • droidcon Team
    • How to Hold a Droidcon
  • Android Careers
Sign In

Global CSS

 

What the Flows: Build an Android app using Flows, Live Data, and MVVM architecture

 

 
Shivam Dhuria
Published: August 07, 2020
Tweet
Share
 

Knowledge of Retrofit, Room and Coroutines is a must for this guide.

 

 

In this tutorial We will build an app that fetches dog breeds from DogApi using Retrofit and then save it to database using Room. We will then use Flows to display the list of dogs from the database.

 

Let’s get Started! 🏁

First things first.

What are flows and when do you use one?

 

A flow is cold asynchronous data stream that sequentially emits values and completes normally or with an exception.

 

This basically means that you should use flows when there’s a stream of data to be emitted. This is very similar to Rx Java if you’re familiar to it.

Another question that might arise at this point now is that what is this stream of data?

Now requests (that you’d make from repository layer) are mainly of two types — One shot or Streams. To explain this I’ll use the same example as Google.

Think of a Tweet. Now the tweet itself is a One Shot Request. You only need to fetch it once and you’re done.You can easily do it using suspend functions. However the number of likes, retweets and comments are a stream of data. You’ll need to refresh them in a loop(say every 30 seconds) to get the updated value. This is the perfect situation to use flows.(More on this later)

 

Why not just use Live Data instead?

There’s nothing wrong in using live data. In your repository layer, you can always do —

 

 

However flows are much easier to use and are specifically built for this purpose. On top of that flows also have certain operators that make it a breeze to transform, combine flows and much more. They are just more powerful using very little code.

 

Start Building

On pressing the “Load More” button in the MainActivity ,we will make a network request to fetch a Dog breed using the Dog API. If the request is successful, we will then save it to the database. This is a One Shot Request.

In the MainActivityApi file, write this function.(ApiResponse is a wrapper class which we need to use for Response from DogAPI, Check here)

 

@GET("breeds/image/random")
suspend fun getRandomDogBreed(): ApiResponse<String>

 

Now in MainActivityRepository.kt, add this function:

 

 

safeApiCall is an extension function I created that handles HTTP Exceptions from the API and wraps the result in a ResultWrapper. If the API request is successful, we save it into the database and then return wrapped Result at the end.

 

dog?.run { dogDao.save(this) }

 

Where dogDao is an interface with a suspend function save

 

 

Now call the above function from the ViewModel:

 

 

And now from the MainActivity.kt, set up an On Click listener which triggers the request and also observe the fetchedLiveData for results. If you notice carefully I only use this to show the status of the request(Loading, No internet Connection) and not the fetched data.

 

 

Setting up Flows

In the DogDao.kt interface define this function:

 

@Query("SELECT * FROM dog")
fun loadAllDogsFlow(): Flow<List<Dog>>

 

Room 2.2 has out of the box support for flows. The above method will return a flow of lists of dogs. When the Load more button is pressed in the view, a new dog is added to the database and since the list of the dogs in the database is dynamic (stream), a flow is a perfect choice for this.

 

In another words we need to use flow in this case because the list of dogs in the database will keep updating.

 

Now call this method from MainActivityRepository.kt:

val dogListFlow = dogDao.loadAllDogsFlow()

Now in the MainViewmodel.kt, we need to convert this flow into Live data which we’ll then observe from the view:

 

 

 

asLiveData() is an extension function that collects the flow and emits it as live data.

Now finally in the MainActivity.kt, observe the above live data:

 

 

 

Since this guide is specifically for learning flows, I am not adding code for adapters or layout. You can find the entire code at GitHub.

At this point you have have a working app that displays data from database (which is Single Source of Truth) using flows which can be updated by executing a one shot request by pressing the “Load More” button in the view.

 

Image for post

 

Combining Flows

Now in RemoteDataSource.kt let’s set up another flow that emits a list of top (random actually) 20 dog breeds every two seconds(in a real life use case scenario this could be a network request):

 

 

Now in MainActivityRepositoty.kt, combine the above flow with the flow of list of dogs from the database using combine operator:

 

 

  • Combine(){} returns a flow whose values are generated with transform function by combining the most recently emitted values by each flow.
  • While flowOn(context: CoroutineContext) changes the context where the flow is to be executed and affects only preceding operators that do not have it’s own context. This basically means the function applyTopDogsToDatabaseList extension function runs in the Dispatchers.Default thread because we used .flowOn(Dispatchers.Default) .
  • .conflate() makes sure that emitter is never suspended due to a slow collector, but collector always gets the most recent value emitted.

 

And That’s it. ✅

You have now built an app that fetches a dog breed using a one shot request, saves it to the database and then displays the list of dogs in database using flows, combines it with another flow that emits every two seconds and then displays the list of dogs in the MainActivity.

The Top Dogs (which keeps changing every two seconds) are represented by pink background in the below GIF.

 

 

Shivamdhuria/flows_guide

Contribute to Shivamdhuria/flows_guide development by creating an account on GitHub.

github.com

 

In Part 2 of this guide, We will implement a search bar to query the dog breeds using Channels and Flows. (Link Here)

 

Image for post

 

 

 

Tags: Android,Android App Development,AndroidDev,Kotlin Coroutines,Flow

 

View original article at: 


 

Originally published: July 22, 2020

Android News
Our Engineering Roadmap
Our Engineering Roadmap

By Mark Ng

We just completed our engineering road map for our Android apps at Australia Post. Each year we get together and try to decide on what we are going to do from an engineering perspective for the next 12 months. Each team gets to decide on what should be done now, what they want to complete by the end of the year and whats on the horizon for next year.

By ProAndroidDev -
Android News
Android Activity Lifecycle considered harmful
Android Activity Lifecycle considered harmful

By Eric Silverberg

The Android activity lifecycle is one of the first architectural concepts learned by a new Android developer. Ask any Android dev and they’ll likely all have seen this handy diagram from Google: 

By ProAndroidDev -
Android News
Our Safe Approach to Android Jetpack Navigation in a Multi-Modular App
Our Safe Approach to Android Jetpack Navigation in a Multi-Modular App

By Alejandro Weichandt

It has been a year since we started working on the Android version of the mobile app at Sync. During that year, we faced more than once that moment when we had to choose which path to follow on an Architectural decision. This story is about Navigation.

By ProAndroidDev -
Android News
Custom KotlinX Serializers
Custom KotlinX Serializers

By Jobin Lawrance

Let’s say we have a third-party class that we are using as a type in one of our data class that we want to be serialized, then we have to write a custom serializable for @Serializable to work.

 

By ProAndroidDev -
droidcon News

Tech Showcases,

Developer Resources &

Partners

/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/home-details/EmployerBrandingHeader
EmployerBrandingHeader
https://jobs.droidcon.com/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/jobs-droidcon/jobs.droidcon.com
jobs.droidcon.com

Latest Android Jobs

http://www.kotlinweekly.net/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/kotlin-weekly/Kotlin Weekly
Kotlin Weekly

Your weekly dose of Kotlin

https://proandroiddev.com/
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/pad/ProAndroidDev
ProAndroidDev

Android Tech Blogs, Case Studies and Step-by-Step Coding

/detail?content-id=/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Zalando/Zalando
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Zalando/Zalando
Zalando

Meet one of Berlin's top employers

/detail?content-id=/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Academy for App Success/Academy for App Success
/portal/rest/jcr/repository/collaboration/Groups/spaces/droidcon_hq/Documents/public/employerbranding/Academy for App Success/Academy for App Success
Academy for App Success

Google Play resources tailored for the global droidcon community

Follow us

Team droidcon

Get in touch with us

Write us an Email

 

 

Quicklinks

> Code of Conduct

> Terms and Conditions

> How to hold a conference

> FAQs

> Imprint

Droidcon is a registered trademark of Mobile Seasons GmbH Copyright © 2020. All rights reserved.

powered by Breakpoint One