Realm: add PagedList implementation
This commit is contained in:
parent
52ebe74302
commit
82180304ef
@ -0,0 +1,67 @@
|
|||||||
|
package org.matrix.android.sdk.internal.database.pagedlist
|
||||||
|
|
||||||
|
import androidx.paging.DataSource
|
||||||
|
import io.realm.kotlin.Realm
|
||||||
|
import io.realm.kotlin.notifications.UpdatedResults
|
||||||
|
import io.realm.kotlin.query.RealmQuery
|
||||||
|
import io.realm.kotlin.query.RealmResults
|
||||||
|
import io.realm.kotlin.types.RealmObject
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.cancelChildren
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
|
||||||
|
internal class RealmTiledDataSource<T : RealmObject> internal constructor(
|
||||||
|
realm: Realm,
|
||||||
|
queryBuilder: (Realm) -> RealmQuery<T>,
|
||||||
|
coroutineScope: CoroutineScope
|
||||||
|
) :
|
||||||
|
TiledDataSource<T>() {
|
||||||
|
|
||||||
|
class Factory<T : RealmObject>(
|
||||||
|
private val realm: Realm,
|
||||||
|
private val queryBuilder: (Realm) -> RealmQuery<T>,
|
||||||
|
private val coroutineScope: CoroutineScope,
|
||||||
|
) : DataSource.Factory<Int, T>() {
|
||||||
|
|
||||||
|
override fun create(): DataSource<Int, T> {
|
||||||
|
val childScope = CoroutineScope(SupervisorJob() + coroutineScope.coroutineContext)
|
||||||
|
return RealmTiledDataSource(realm, queryBuilder, childScope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val results: RealmResults<T>
|
||||||
|
|
||||||
|
init {
|
||||||
|
addInvalidatedCallback {
|
||||||
|
coroutineScope.coroutineContext.cancelChildren()
|
||||||
|
}
|
||||||
|
results = queryBuilder(realm).find()
|
||||||
|
results.asFlow()
|
||||||
|
.onEach { resultsChange ->
|
||||||
|
when (resultsChange) {
|
||||||
|
is UpdatedResults -> invalidate()
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.launchIn(coroutineScope)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun countItems(): Int {
|
||||||
|
return results.size
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadRange(startPosition: Int, count: Int): List<T> {
|
||||||
|
val size = countItems()
|
||||||
|
if (size == 0) return emptyList()
|
||||||
|
return buildList {
|
||||||
|
val endPosition = minOf(startPosition + count, size)
|
||||||
|
for (position in startPosition until endPosition) {
|
||||||
|
results.getOrNull(position)?.also { item ->
|
||||||
|
add(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
package org.matrix.android.sdk.internal.database.pagedlist
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import androidx.paging.PositionalDataSource
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
public abstract class TiledDataSource<T : Any> : PositionalDataSource<T>() {
|
||||||
|
|
||||||
|
public abstract fun countItems(): Int
|
||||||
|
|
||||||
|
public abstract fun loadRange(startPosition: Int, count: Int): List<T>?
|
||||||
|
|
||||||
|
@SuppressLint("RestrictedApi") // For computeInitialLoadPosition, computeInitialLoadSize
|
||||||
|
override fun loadInitial(
|
||||||
|
params: LoadInitialParams,
|
||||||
|
callback: LoadInitialCallback<T>
|
||||||
|
) {
|
||||||
|
val totalCount = countItems()
|
||||||
|
if (totalCount == 0) {
|
||||||
|
callback.onResult(emptyList(), 0, 0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val firstLoadPosition = computeInitialLoadPosition(params, totalCount)
|
||||||
|
val firstLoadSize = computeInitialLoadSize(params, firstLoadPosition, totalCount)
|
||||||
|
|
||||||
|
val list = loadRange(firstLoadPosition, firstLoadSize)
|
||||||
|
if (list != null && list.size == firstLoadSize) {
|
||||||
|
callback.onResult(list, firstLoadPosition, totalCount)
|
||||||
|
} else {
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<T>) {
|
||||||
|
val list = loadRange(params.startPosition, params.loadSize)
|
||||||
|
if (list != null) {
|
||||||
|
callback.onResult(list)
|
||||||
|
} else {
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user