Last active
May 24, 2022 04:31
-
-
Save michaelbukachi/0c7f18bdeaf4bdb12b5527304d6cdbc0 to your computer and use it in GitHub Desktop.
Realm Coroutines
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import io.realm.* | |
import io.realm.kotlin.where | |
import kotlinx.coroutines.GlobalScope | |
import kotlinx.coroutines.launch | |
import kotlinx.coroutines.suspendCancellableCoroutine | |
import kotlin.coroutines.resume | |
import kotlin.coroutines.resumeWithException | |
private suspend fun <T: RealmObject, S: RealmQuery<T>> findAllAwait(query: S): RealmResults<T> = suspendCancellableCoroutine { continuation -> | |
val listener = RealmChangeListener<RealmResults<T>> { t -> continuation.resume(t) } | |
query.findAllAsync().addChangeListener(listener) | |
} | |
private suspend fun <T: RealmObject, S: RealmQuery<T>> findFirstAwait(query: S): T? = suspendCancellableCoroutine { continuation -> | |
val listener = RealmChangeListener { t: T? -> continuation.resume(t) } | |
query.findFirstAsync().addChangeListener(listener) | |
} | |
private suspend fun executeAsync(realm: Realm, block: (Realm) -> Unit): Unit = suspendCancellableCoroutine { continuation -> | |
realm.executeTransactionAsync({ block(it) }, { continuation.resume(Unit) }, { continuation.resumeWithException(it) }) | |
} | |
suspend fun <S: RealmObject> RealmQuery<S>.await() = findAllAwait(this) | |
suspend fun <S: RealmObject> RealmQuery<S>.awaitFirst() = findFirstAwait(this) | |
suspend fun Realm.transactAwait(block: (Realm) -> Unit) = executeAsync(this, block) | |
class TestObject(val name: String? = "") : RealmObject() | |
fun test() { | |
GlobalScope.launch { | |
val realm = Realm.getDefaultInstance() | |
val result = realm.where<TestObject>().awaitFirst() | |
val results = realm.where<TestObject>().await() | |
realm.transactAwait(Realm.Transaction { | |
val testObject = TestObject(name = "Some Test") | |
it.copyToRealm(testObject) | |
}) | |
} | |
} |
wouldn't it be better to also remove the listener when there is an exception? i'm not super strong with all coroutine conventions / features yet,
is there reason why it is not necessary?
another thing is that i believe it would be better to use inline functionality here as well
suspend inline fun <reified T : RealmObject, reified S : RealmQuery<T>> findAllAwait(query: S): RealmResults<T> = suspendCancellableCoroutine { continuation ->
val listener = RealmChangeListener<RealmResults<T>> { t -> continuation.resume(t) }
val results = query.findAllAsync()
results.addChangeListener(listener)
continuation.invokeOnCancellation {
results.removeChangeListener(listener)
}
}
suspend inline fun <reified T : RealmObject, reified S : RealmQuery<T>> findFirstAwait(query: S): T? = suspendCancellableCoroutine { continuation ->
val listener = RealmChangeListener { t: T? -> continuation.resume(t) }
val results = query.findFirstAsync()
results.addChangeListener(listener)
continuation.invokeOnCancellation {
results.removeChangeListener(listener)
}
}
suspend fun Realm.transactAwait(block: (Realm) -> Unit): Unit = suspendCancellableCoroutine { continuation ->
executeTransactionAsync({ block(it) }, { continuation.resume(Unit) }, { continuation.resumeWithException(it) })
}
suspend inline fun <reified S : RealmObject> RealmQuery<S>.await() = findAllAwait(this)
suspend inline fun <reified S : RealmObject> RealmQuery<S>.awaitFirst() = findFirstAwait(this)
Hi @kibotu. Thanks for pointing that out. It's important do cleanup after cancellation. Also, I created a library for this at https://github.com/michaelbukachi/realm-koroutines. Would nice if you could raise an issue over there.
cool thanks for sharing
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@kibotu First time hearing about
freeze()
. I haven't visited their site in a while. Let me experiment with it and see what can be done with it.