Skip to content

Instantly share code, notes, and snippets.

@eduardb
Last active January 23, 2023 17:18
Show Gist options
  • Save eduardb/8916ac63d7a279b48857d9abc1f4546e to your computer and use it in GitHub Desktop.
Save eduardb/8916ac63d7a279b48857d9abc1f4546e to your computer and use it in GitHub Desktop.
shareIn scope
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
interface DataSource {
fun query(args: QueryArgs): Foo
val changedKeys: SharedFlow<Set<String>>
}
interface QueryArgs
val QueryArgs.keys: Set<String>
get() = setOf("")
class Foo
class Repo(private val dataSource: DataSource) {
// does this need closing? or should function-inject viewModelScope instead?
private val scope = MainScope()
fun queryAndWatch(args: QueryArgs): SharedFlow<Foo> {
return flow {
emit(dataSource.query(args))
emitAll(
// this is also a SharedFlow
dataSource.changedKeys
.filter { changedKeys -> changedKeys.intersect(args.keys).isNotEmpty() }
.map { dataSource.query(args) }
)
}.shareIn(scope, SharingStarted.WhileSubscribed(5_000), replay = 1)
}
}
class MyVM(repo: Repo, args: QueryArgs) : ViewModel() {
private val data: SharedFlow<Foo> = repo.queryAndWatch(args)
val foo: StateFlow<String> = data.map { "foo ${toString()}" }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), "")
val bar: StateFlow<String> = data.map { "bar ${toString()}" }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), "")
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="vm" type="MyVM" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@{vm.foo}" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@{vm.bar}" />
</LinearLayout>
</layout>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment