Search code examples
androiddatabasekotlinmvvmretrofit

When I should use Flow, and when should I use Corountines?


I've started to learning some more "advanced" stuff, and I'm a bit overwhelmed. I'm not sure, if I understand things correctly. I'd like to know, when I should use the Flow, and when Corountines.

Let's say that I have two apps. The first one have a few fragments within it. Every fragment will make different api call, for example:

  • current forecast

  • weekly forecast

  • monthly forecast

api call will be done atleast once, since user can change data needed to perform an api call, for example - different city. Should I use corountines with this type of application?

The second application, will be based on database operations, let's say it'll be some kind of "journal", where user will be adding his meals, with some macronutrients. Since this application will be mostly about database, should I use Flow then?

What if I'll have an app, that store some data in database, but also performs the api calls? Should I "mix" flows (for database operations), and corountines (for api operations)?


Solution

  • To add to what Tenfour04 is saying, coroutines are about concurrency - they allow you to do multiple tasks "at the same time" instead of having a single task where each step can only take place when the step before has finished. That means you can start tasks that go off and take a while to produce a result, while the current task continues instead of having to wait for it (which is called blocking).

    So when you're using a coroutine, you're able to do stuff that "takes a while". There are two main patterns for this:

    • things that return a single result, or no result at all
    • things that return multiple results over time

    The first includes coroutines created with launch (no result) or async (returns a value when completed), and also suspend functions which are just normal functions that have to be called from within a coroutine. They run, taking some time, and potentially return a value when finished.

    The second, multiple results over time, is where flow comes in. This is something that emits values over time, and can terminate when it's finished, or stay active, potentially emitting values forever. You can think of it like a List or Sequence, but one where you can't access the elements on demand - they're produced by the flow as and when they're ready.

    And this is why you have to collect them in the context of a coroutine - you can't block execution of your main code waiting for these items to be emitted, especially when collection can potentially never end! It's not just "this might take some time to finish" - it might never finish at all. That's why it needs to be done concurrently inside a coroutine task that can wait around for items, and react to them by doing something useful.

    Lots of libraries in Android use Flow already - one example is Room, where database queries can return a Flow of items. What this means in practice is it will produce updates to that query over time, as the DB changes, so you have a data source you can collect from. Or you might just collect the first value and drop the flow entirely! But either way, you need to handle that collection within a coroutine.


    As far as your specific question goes, your app architecture really depends on what you want to do. I think this video by the Android team does a great job explaining how flows work as a data source, how you design around the reactive model, and how you divide your app into different layers and connect them with flows.

    I'd really recommend reading through the Kotlin coroutines guide before you look too closely at the Android side of things, just because that adds extra complications and things you need to be aware of (like lifecycles and the scopes associated with them). Once you have the general idea down, here's another video (or an older article) explaining how to collect from flows in your lifecycle-aware components (usually Activities and Fragments). This is just about the end point though, the process of collection by the UI where you need to worry about if things are paused, stopped etc. Most of the time, you're just connecting things up normally, data sources to things that collect and process them and produce their own data, like the first video describes!