Does anyone know of examples of (or have any tips ...
# coroutines
r
Does anyone know of examples of (or have any tips regarding) using coroutines + Flow for a simple, local data source in an application? 🧵
I wrote a small Compose multiplatform app that let's you choose directories full of APKs on your machine, shows their absolute paths in a list, and writes a manifest file about them using information from aapt. The app has an
ApkDataRepository
class to manage APK data, and the data source is just a private
MutableStateFlow
property of the repository itself. In trying to adhere to advice from different things I've read, my repository exposes the data as a
Flow
and CRUD methods as suspending functions. IntelliJ is indicating that all of the suspend modifiers on my
ApkDataRepository
functions are redundant so I'm feeling like I did something wrong there. I'm trying out another simple app and would like to learn from my past mistakes, so any advice or examples is appreciated. I've considered that maybe suspending functions and
Flow
are just overkill for such a simple app, but at the same time hope that it's possible to use contrived, low-complexity use cases like this to better understand coroutine and Flow concepts.
g
IntelliJ is indicating that all of the suspend modifiers on my
ApkDataRepository
functions are redundant so I’m feeling like I did something wrong there
It indeed looks as something wrong suspend function needed only if it calls another suspend function And 2 main reasons why you may need suspend function is: 1. You work with some asyncronous API (based on callbacks, observer pattern etc) and use coroutine adapater to work with it 2. Use suspend functions to run some work in a separate thread using coroutines dispatchers
Hard to say from your description how you should use suspend functuions, but looks that you use APIs which access IO (disk in your case), so it means that you probably shouldn’t call them from main thread, so wrapping calls to withContext(Dispatchers.IO) sounds reasonable
Flow can be useful even with the most simple app as an observable abstraction between your View and business logic
r
I suppose what I'm aiming for is making my data layer's API asynchronous, even if in reality it's just updating a
Map
or some other data structure in memory. In theory it would be easy enough to plug-in a database or network data source if all my data layer code is structured well enough, but I was hoping to not have to start with that right from the beginning while I learn my way around.
Trying to understand Compose, Flow, and coroutines all at once has been unfortunately more challenging than I hoped, so I am trying to write like a I have an asynchronous data source even though, at the moment, there isn't one.
g
I suppose what I’m aiming for is making my data layer’s API asynchronous, even if in reality it’s just updating a
Map
suspend function by itself doesn’t make your code asyncroonous, but if you use something like a standalone coroutine (launch/async) or some flow to use it to update your Map, it will emulate case with network or database
r
I'm trying out a data source that is backed by files. For example, a
create
operation would serialize a JSON object of default values to disk. A
get
would deserialize the file, and then emit a single value on a
Flow
. An
update
would re-serialize the file with updated values, and
delete
would remove a particular file.
g
Yep, makes sense. IO operation should be wrapped with IO dispatcher, same as in another thread where we discussing how to wrap blocking function