mirror of https://github.com/tasks/tasks
Android Wear paging improvements
parent
dd6ba730e9
commit
a8977f02fe
@ -1,36 +1,85 @@
|
|||||||
package org.tasks.presentation
|
package org.tasks.presentation
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.paging.PagingSource
|
import androidx.paging.PagingSource
|
||||||
|
import androidx.paging.PagingSource.LoadParams
|
||||||
|
import androidx.paging.PagingSource.LoadParams.Append
|
||||||
|
import androidx.paging.PagingSource.LoadParams.Prepend
|
||||||
|
import androidx.paging.PagingSource.LoadParams.Refresh
|
||||||
import androidx.paging.PagingState
|
import androidx.paging.PagingState
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
private const val INITIAL_ITEM_COUNT = -1
|
||||||
|
|
||||||
class MyPagingSource<T : Any>(
|
class MyPagingSource<T : Any>(
|
||||||
private val fetch: suspend (position: Int, limit: Int) -> List<T>?,
|
private val fetch: suspend (position: Int, limit: Int) -> Pair<Int, List<T>>,
|
||||||
) : PagingSource<Int, T>() {
|
) : PagingSource<Int, T>() {
|
||||||
|
|
||||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, T> {
|
private var itemCount = INITIAL_ITEM_COUNT
|
||||||
val position = params.key ?: 0
|
|
||||||
val limit = params.loadSize
|
|
||||||
|
|
||||||
|
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, T> {
|
||||||
return try {
|
return try {
|
||||||
val items = withContext (Dispatchers.IO) {
|
val key = params.key ?: 0
|
||||||
fetch(position, limit) ?: emptyList()
|
val limit = getLimit(params, key)
|
||||||
|
val offset = getOffset(params, key, itemCount)
|
||||||
|
val (newCount, data) = fetch(offset, limit)
|
||||||
|
if (itemCount == INITIAL_ITEM_COUNT) {
|
||||||
|
itemCount = newCount
|
||||||
}
|
}
|
||||||
|
val nextPosToLoad = offset + data.size
|
||||||
LoadResult.Page(
|
val nextKey =
|
||||||
data = items,
|
if (data.isEmpty() || data.size < limit || nextPosToLoad >= itemCount) {
|
||||||
prevKey = if (position <= 0) null else position - limit,
|
null
|
||||||
nextKey = if (items.isEmpty()) null else position + limit
|
} else {
|
||||||
|
nextPosToLoad
|
||||||
|
}
|
||||||
|
val prevKey = if (offset <= 0 || data.isEmpty()) null else offset
|
||||||
|
return LoadResult.Page(
|
||||||
|
data = data,
|
||||||
|
prevKey = prevKey,
|
||||||
|
nextKey = nextKey,
|
||||||
|
itemsBefore = offset,
|
||||||
|
itemsAfter = maxOf(0, itemCount - nextPosToLoad)
|
||||||
)
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("MyPagingSource", "${e.message}\n${e.stackTrace}")
|
|
||||||
LoadResult.Error(e)
|
LoadResult.Error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getRefreshKey(state: PagingState<Int, T>): Int {
|
override fun getRefreshKey(state: PagingState<Int, T>): Int? = state.getClippedRefreshKey()
|
||||||
return ((state.anchorPosition ?: 0) - state.config.initialLoadSize / 2).coerceAtLeast(0)
|
}
|
||||||
|
|
||||||
|
private fun <Value : Any> PagingState<Int, Value>.getClippedRefreshKey(): Int? {
|
||||||
|
return when (val anchorPosition = anchorPosition) {
|
||||||
|
null -> null
|
||||||
|
else -> maxOf(0, anchorPosition - (config.initialLoadSize / 2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLimit(params: LoadParams<Int>, key: Int): Int {
|
||||||
|
return when (params) {
|
||||||
|
is Prepend ->
|
||||||
|
if (key < params.loadSize) {
|
||||||
|
key
|
||||||
|
} else {
|
||||||
|
params.loadSize
|
||||||
|
}
|
||||||
|
else -> params.loadSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOffset(params: LoadParams<Int>, key: Int, itemCount: Int): Int {
|
||||||
|
return when (params) {
|
||||||
|
is Prepend ->
|
||||||
|
if (key < params.loadSize) {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
key - params.loadSize
|
||||||
|
}
|
||||||
|
is Append -> key
|
||||||
|
is Refresh ->
|
||||||
|
if (itemCount != INITIAL_ITEM_COUNT && key >= itemCount) {
|
||||||
|
maxOf(0, itemCount - params.loadSize)
|
||||||
|
} else {
|
||||||
|
key
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue