Skip to content

Instantly share code, notes, and snippets.

@datikaa
Last active February 15, 2024 21:27
Show Gist options
  • Save datikaa/3b98aea99a8870f2b5bdf5b9a611bd1b to your computer and use it in GitHub Desktop.
Save datikaa/3b98aea99a8870f2b5bdf5b9a611bd1b to your computer and use it in GitHub Desktop.
import io.realm.*
import io.realm.kotlin.toFlow
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
/**
* Returns a [Flow] with all of the results of the [RealmQuery], while drops every offer that is not
* loaded already. This makes it easy to be used with [kotlinx.coroutines.flow.first]. Be aware that
* the [Realm] object must be on a thread with a looper.
*
*
* Example:
* ```
* realmInstance.where<Foo>()
* .flowAll()
* .map { results -> doExpensiveWork(results) }
* .flowOn(Dispatchers.IO)
* .onEach { flowResults ->
* // ...
* }.launchIn(Dispatchers.Main)
* ```
*
*
* @param[detach] If true, [Realm.copyFromRealm] will be called on every element. Defaults to true.
*/
fun <T : RealmModel> RealmQuery<T>.flowAll(detach: Boolean = true): Flow<List<T>> = findAllAsync()
.toFlow()
.flowOn(Dispatchers.Main)
.dropWhile { !it.isLoaded }
.map { if (detach) it.copyFromRealm() else it }
/**
* Same as [flowAll] but limited to only one object, which is nullable.
*
* Example:
* ```
* val foo: List<Foo> = realmInstance.where<Foo>()
* .flowAll()
* .first()
* ```
*
* @param[detach] If true, [Realm.copyFromRealm] will be called on every element. Defaults to true.
*/
fun <T : RealmModel> RealmQuery<T>.flowFirst(detach: Boolean = true): Flow<T?> = limit(1)
.flowAll(detach)
.map { it.firstOrNull() }
/**
* Creates a detached copy from this [RealmResults].
*/
fun <T : RealmModel> RealmResults<T>.copyFromRealm() : List<T> {
return Realm.getInstance(realm.configuration).use {
it.copyFromRealm(this)
}
}
/**
* Creates a detached copy from this [RealmModel]
*/
fun <T : RealmModel> T.copyFromRealm(): T = Realm.getDefaultInstance().use {
it.copyFromRealm(this)
}
/**
* Get's a default [Realm] instance on [Dispatchers.Main], and passes it inside the lambda where
* you need to return with a [Flow].
*
* Example:
* ```
* val foo: Flow<List<Foo>> = autoCloseRealmFlow { realm ->
* realm.where<Foo>().flowAll()
* }
* ```
* @param[context] The [CoroutineContext] where the [Realm] instance will be initialized
*/
fun <T> autoCloseRealmFlow(context: CoroutineContext = Dispatchers.Main, query: (Realm) -> Flow<T>): Flow<T> = flow {
emitAll(Realm.getDefaultInstance().use(query))
}.flowOn(context)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment