https://kotlinlang.org logo
#coroutines
Title
# coroutines
j

Johnjake Talledo

08/21/2021, 9:39 AM
Hello guys do you have any example of coroutine 
SharedFlows
 
shareIn
 in github or gitlab, I couldn't find good resources or articles with a sample. What I am trying to achieve is combine(flow1, flow2) with 
shareIn
, so I only need to
getfetch
once and share this to at least 3 fragments. I really appreciate if someone could help. Best Regards to all.
a

Alexandre Brown

08/21/2021, 4:54 PM
Hello @Johnjake Talledo , here is an example of
shareIn
or `stateIn`(it's the same principle)
Copy code
class MyClass(override val coroutineContext: CoroutineContext = Dispatchers.Default) : CoroutineScope {

private val myPresentation: SharedFlow<Presentation> = combine(
        myRepository1.myStateFlow,
        myRepository2.myStateFlow,
        myRepository3.myStateFlow
    ) { a, b, c ->
        myPresenter.present(a,b,c)
    }.shareIn(this, SharingStarted.Lazily)

...

fun getAbc() = myPresentation

}
To get a StateFlow instead you would simply change the code to
myPresentation.stateIn(this, SharingStarted.Lazily, presentDefaultValue())
Depending on what you want you might want to do
shareIn
only once in a property(1 instance) or in the function call (1 instance per call). In most cases having 1 instance is probably what you want but make sure it works with any 3rd party extension like
asLiveData
etc.
❤️ 1
u

ursus

08/22/2021, 11:16 AM
watch out how you call getAbc, you could get multiple instance and thuss no sharinv
❤️ 1
j

Johnjake Talledo

08/22/2021, 12:34 PM
@Alexandre Brown Thanks a lot for this.
@ursus Can you please explain. Thank you.
u

ursus

08/22/2021, 12:36 PM
in order to use shared flow you need to collect the same instance
💯 1
otherwise there is no point in shareing
j

Johnjake Talledo

08/22/2021, 12:40 PM
Yeah I haven't try it yet but my idea was collect the same instance in different fragment.
a

Alexandre Brown

08/22/2021, 12:40 PM
Hello @ursus , that's precisely what I discussed in the second part of the initial message. It depends on what you want. I would say make sure that using one instance works for your use case. For example if using with the .asLiveData().
In most cases one instance should be what you go for but make sure it works with any 3rd party implementation (eg: asLiveData) and that you don't get collection exception. To use 1 instance @Johnjake Talledo simply add to
shareIn
at the end of the property and return that property in the function call (see the updated code)
❤️ 1
j

Johnjake Talledo

08/22/2021, 12:43 PM
@Alexandre Thank you, I will try it now and let you know, once again thank you.
👍 1
@Alexandre Brown What does the
myPresenter.present(a,b,c)
do? Is this where you implement eg:
asLiveData
in my case I use
MutableSharedFlow
?
I am not sure if this correct.
a

Alexandre Brown

08/23/2021, 9:46 AM
@Johnjake Talledo The
myPresenter.present
is just hypothetical code that represents some transform. Usually we use combine to listen to multiple flows and when we want to receive updates even if not all the flow changed. Then inside the lambda of the combine we'd use the various lambda parameters to perform some transformation (eg: Create a data class with some info from the various flows values). If you don't want to merge multiple flows into 1 result and be notified of each updates in a single place then perhaps you don't need combine at all. In your case it's much simpler. You can simply do
private val deliveryUpdates: SharedFlow = repository.getDeliverable(token, "id", "name,count,...").shareIn(this, SharingStarted.Lazily)
Same principle for the
restaurentUpdates
❤️ 1
j

Johnjake Talledo

08/24/2021, 1:36 AM
Thanks
👍 1
@Alexandre Brown I have question regarding
shareIn
or
Hot flows
when the app goes background does it still continue to emit if the end point has a new item or value?
u

ursus

08/24/2021, 9:25 AM
Flow knows nothing of androidl lifecycle
❤️ 1
a

Alexandre Brown

08/24/2021, 11:28 AM
Hello @Johnjake Talledo, as mentioned by @ursus, Flows are not lifecycle aware. That being said, when using Android databinding you can now (it's very recent) use StateFlow in your ViewModel and they will be lifecycle aware when used in data binding (make sure to specify the lifecycle owner of the daya binding). So Data binding currently supports StateFlow and LiveData. You can learn more here : https://developer.android.com/topic/libraries/data-binding/observability#lifecycle-objects
❤️ 1
j

Johnjake Talledo

08/24/2021, 12:53 PM
@Alexandre Brown and @ursus Thanks
👍 2
@Alexandre Brown unfortunately I do not use databinding only viewbinding, ah I see so I just make flows lifecycle aware, in my app actually its a complex network calls, I had at least 5 network calls and then map this to data classes, on one page that I want to optimized, I just use the
getDeliverables
and
getRestuarant
as a test. I was more familiar with
zip
in
rxJava
and
combine
is equivalent of
zip
and when I read about
ShareIn
this probably solve my problem, what I wanted to achieve is to continue the
upstream
to fetch data from api, then collect this in other fragment, so I will not be calling the same expensive network calls because it takes sometimes 17 to 25 milliseconds before data on recycleview will show up.