Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Coroutine flow support #233

Closed
wants to merge 6 commits into from
Closed

Conversation

emmano
Copy link

@emmano emmano commented Sep 11, 2021

This should help with adding support for coroutines as mentioned in #231

A couple of things to note:

  • I had to use the experimental channel field in callbackFlow{} in order to comply to the onError argument for FormulaRuntime. Using cancel() on the ProducerScope is not possible since it takes a CancellableException and not a Throwable.
  • The documentation for ViewModel integration suggests to dispose of the "producer" observable inside onClear() and to dispose of the consumer subscirption inside onDestroy() of the Activity. If I am not mistaken it seems that this can lead to two dangerous scenarios:
    1. The producer stream can trigger UI updates when the Activity/Fragment is not visible. This can be solved by disposing of the consumer inside onStop().
    1. The producer stream might be wasting resources since it is kept alive until the ViewModel is cleared. For example, if the producer stream depends on a stream that monitors network connectivity, the producer stream will still emit events even if the consumer has been disposed, hence wasting resources (i.e. battery). To address this issue, in one of the samples I added, I am using repeatOnLifecycle{} in combination with SharingStarted.WhileSubscribed(). This approach not only stops/starts collection, but also cancels the producer on the required lifecycle when there are no more collectors. repeatOnLifecycle{} uses an alpha release of the lifecycle runtime dependency.
  • I added a test for StopWatchFormula just as an example of how testing a flow might look like. It is probably better to add Flow testing capabilities to formula-test just like it is done for rx.

@emmano emmano force-pushed the coroutine-flow-support branch 2 times, most recently from 2f10a0e to 3261255 Compare September 13, 2021 13:24
@Test
fun `increment 5 times`() = test {

StopwatchFormula(this)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to have such a tests within formula-coroutines module to cover toFlow() and FlowStream.fromFlow {}.

Copy link
Author

@emmano emmano Sep 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added tests for FlowRuntime and FlowStream. I know you were trying to decide if it still made sense to have per runtime specific tests, but we can always remove them. I added TestFlow to serve the purpose of Rx's TestObserver. I know square came out with Turbine, but it felt like an overkill.

@Laimiux
Copy link
Collaborator

Laimiux commented Sep 13, 2021

First of all, thank you for this contribution 🙌 Overall, it looks pretty solid.

  • The documentation for ViewModel integration suggests to dispose of the "producer" observable inside onClear() and to dispose of the consumer subscirption inside onDestroy() of the Activity.

We generally want Formula to survive configuration changes and forward navigation.

  • We want to maintain state across configuration changes.
  • We want network requests to persist across configuration changes as well.

This approach has been working well for us, but the issues you bring up are valid.

  • For UI updates, we control the subscription from Activity or Fragment, so we can unsubscribe even though Formula is still running.
  • Regarding wasteful/heavy resources, we haven't run into this issue much, but one option is to control it at the resource level. Formula keeps running, but the resource stream receives Activity lifecycle events and pauses when app is in the background.

I added a test for StopWatchFormula just as an example of how testing a flow might look like. It is probably better to add Flow testing capabilities to formula-test just like it is done for rx.

I have been thinking about this a little bit, not yet sure what is the best option here. For more context, the RxJava version is used only internally within formula-test. My current thinking is that tests shouldn't really care about which runtime is used as they should behave equivalently. One caveat is that Coroutines has better support for nullable inputs and outputs where RxJava has to force non-null values currently.

@emmano emmano force-pushed the coroutine-flow-support branch 2 times, most recently from 8f128d2 to ec4739d Compare September 13, 2021 18:58
@emmano emmano force-pushed the coroutine-flow-support branch from 321803f to 87aa472 Compare September 16, 2021 00:53
@Laimiux Laimiux mentioned this pull request Sep 16, 2021
@Laimiux
Copy link
Collaborator

Laimiux commented Sep 16, 2021

Thank you for your contribution @emmano!! I'm going to take it over from here, finish up and merge the changes in #240.

@emmano
Copy link
Author

emmano commented Sep 17, 2021

Thank you for your contribution @emmano!! I'm going to take it over from here, finish up and merge the changes in #240.

No problem! Glad to help!

@Laimiux
Copy link
Collaborator

Laimiux commented Sep 20, 2021

Closing this as we merged #240

@Laimiux Laimiux closed this Sep 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants