Realm: add RealmInstance class
This commit is contained in:
parent
82180304ef
commit
186753f691
@ -0,0 +1,116 @@
|
|||||||
|
package org.matrix.android.sdk.internal.database
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import androidx.paging.LivePagedListBuilder
|
||||||
|
import androidx.paging.PagedList
|
||||||
|
import io.realm.kotlin.MutableRealm
|
||||||
|
import io.realm.kotlin.Realm
|
||||||
|
import io.realm.kotlin.RealmConfiguration
|
||||||
|
import io.realm.kotlin.notifications.ResultsChange
|
||||||
|
import io.realm.kotlin.query.RealmQuery
|
||||||
|
import io.realm.kotlin.types.RealmObject
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.CoroutineStart
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.NonCancellable
|
||||||
|
import kotlinx.coroutines.async
|
||||||
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
|
import kotlinx.coroutines.flow.flatMapConcat
|
||||||
|
import kotlinx.coroutines.flow.flow
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import org.matrix.android.sdk.internal.database.pagedlist.RealmTiledDataSource
|
||||||
|
|
||||||
|
internal typealias RealmQueryBuilder<T> = (Realm) -> RealmQuery<T>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is responsible for managing an instance of realm.
|
||||||
|
* You should make sure to keep this class as a singleton.
|
||||||
|
* You can force opening the realm by calling [open] method.
|
||||||
|
* Otherwise it will be lazily opened when first querying/writing.
|
||||||
|
* Makes sure to call [close] when you don't need the instance anymore.
|
||||||
|
*/
|
||||||
|
internal class RealmInstance(
|
||||||
|
val coroutineScope: CoroutineScope,
|
||||||
|
private val realmConfiguration: RealmConfiguration,
|
||||||
|
coroutineDispatcher: CoroutineDispatcher
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val realm =
|
||||||
|
coroutineScope.async(context = coroutineDispatcher, start = CoroutineStart.LAZY) {
|
||||||
|
Realm.open(realmConfiguration)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun open() {
|
||||||
|
coroutineScope.launch {
|
||||||
|
realm.join()
|
||||||
|
}.join()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun close() = withContext(NonCancellable) {
|
||||||
|
realm.await().close()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : RealmObject> queryResults(
|
||||||
|
realmQueryBuilder: RealmQueryBuilder<T>
|
||||||
|
): Flow<ResultsChange<T>> {
|
||||||
|
return getRealm().flatMapConcat {
|
||||||
|
realmQueryBuilder(it).asFlow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : RealmObject> queryList(
|
||||||
|
realmQueryBuilder: RealmQueryBuilder<T>
|
||||||
|
): Flow<List<T>> {
|
||||||
|
return queryResults(realmQueryBuilder).map {
|
||||||
|
it.list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : RealmObject> queryPagedList(
|
||||||
|
config: PagedList.Config,
|
||||||
|
queryBuilder: RealmQueryBuilder<T>
|
||||||
|
): Flow<PagedList<T>> {
|
||||||
|
|
||||||
|
fun <T> LiveData<T>.asFlow(): Flow<T> = callbackFlow {
|
||||||
|
val observer = Observer<T> { value -> trySend(value) }
|
||||||
|
observeForever(observer)
|
||||||
|
awaitClose {
|
||||||
|
removeObserver(observer)
|
||||||
|
}
|
||||||
|
}.flowOn(Dispatchers.Main.immediate)
|
||||||
|
|
||||||
|
return getRealm().flatMapConcat { realm ->
|
||||||
|
val livePagedList = LivePagedListBuilder(
|
||||||
|
RealmTiledDataSource.Factory(
|
||||||
|
realm = realm,
|
||||||
|
queryBuilder = queryBuilder,
|
||||||
|
coroutineScope = coroutineScope
|
||||||
|
),
|
||||||
|
config
|
||||||
|
).build()
|
||||||
|
livePagedList.asFlow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun <R> write(block: MutableRealm.() -> R): R {
|
||||||
|
return realm.await().write(block)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <R> blockingWrite(block: MutableRealm.() -> R): R {
|
||||||
|
return runBlocking {
|
||||||
|
write(block)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getRealm(): Flow<Realm> = flow {
|
||||||
|
emit(realm.await())
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user