Kotlin Flow for Android: Getting Started

In this tutorial, you’ll learn about the basics of Kotlin Flow, and you’ll build an Android app that fetches weather forecast data using Flow. By Dean Djermanović.

4.8 (35) · 2 Reviews

Download materials
Save for later
Share
You are currently viewing page 4 of 4 of this article. Click here to view the first page.

Querying Locations

Now add the logic for consuming the events from the channel as a Flow:

private val _locations = queryChannel
    //1
    .asFlow()
    //2
    .debounce(SEARCH_DELAY_MILLIS)
    //3
    .mapLatest {
      if (it.length >= MIN_QUERY_LENGTH) {
        getLocations(it)
      } else {
        emptyList()
      }
    }
    //4
    .catch {
      // Log Error
    }

Here's what happens in this block of code:

  1. First, the call to asFlow converts the Channel into a Flow.
  2. Next, debounce() waits for values to stop arriving for a given time period. This is used to avoid processing every single letter typed by users. Users usually type several letters in a row. You don't need to make a network request until the user stops typing. This ensures that you're performing the API call only after 500 milliseconds have passed with no typing!
  3. Then, mapLatest() performs the API call and returns location results. If the original flow emits a new value while the previous API call is still in progress, mapLatest() ensures that computation of the previous block is canceled. mapLatest() performs the API call only if the search query contains at least two characters.
  4. Finally, catch() handles errors.

Add locations to HomeViewModel.kt. This allows you to observe from the activity:

val locations = _locations.asLiveData()

Here you're using asLiveData() to collect values from the origin flow and add transform them to a LiveData instance.

Open HomeActivity.kt and delete the call from onCreate() to homeViewModel.fetchLocationDetails(). Instead observe locations from initObservers():

private fun initObservers() {
  homeViewModel.locations.observe(this, Observer {
    locationAdapter.setData(it)
  })

  ...
}

Once again, build and run the app. Now enter a search query. You'll see the options generated from your query:

Sunzoid With Location Query

Go ahead and tap any of the options. The home screen will display forecast data for a newly selected location.

Why Kotlin Flow

There are already other implementations of the reactive stream specification, such as RxJava. So why use Kotlin Flow? One reason is that you can't use JVM-specific libraries like RxJava in Kotlin multi-platform projects. But Flow is part of the Kotlin language, so it's ideal to use in Kotlin multi-platform projects.

Also, Kotlin Flow has fewer operators, but they are much simpler. A single operator can handle both synchronous and asynchronous logic since the block of code that operators accept can be suspended!

And Kotlin Flow is interoperable with other reactive streams and coroutines. Since it's built on top of coroutines, it provides all the perks of structured concurrency and cancellation. In combination with suspending functions, it produces a simple, readable, and understandable API. It also supports backpressure out of the box.

Where To Go From Here?

You can download the final project using the Download Materials button at the top or bottom of this tutorial.

You've created an app that uses Kotlin Flow for communication between application layers. In the process, you learned what is so special about Kotlin Flow and how it's different from existing solutions. You also used Flow builders to create a Flow. You became familiar with basic operators to transform a stream of data. And finally, you applied terminal operators to consume the values!

To gain more in-depth knowledge about Kotlin Flow, check out our Kotlin Flow: Getting Started video course. You'll learn a lot more about Flow builders, operators, and cancellation. You'll also learn how to work with Flows, change its context, add buffers, combine multiple Flows, and handle exceptions!

We hope you've enjoyed this tutorial! If you have any questions or comments to share, please join the forum discussion below. :]