138 lines
3.9 KiB
Kotlin
138 lines
3.9 KiB
Kotlin
package com.aiosman.riderpro.data
|
|
|
|
import androidx.paging.PagingSource
|
|
import androidx.paging.PagingState
|
|
import com.aiosman.riderpro.model.MomentItem
|
|
import com.aiosman.riderpro.test.TestDatabase
|
|
import java.io.IOException
|
|
import kotlin.math.min
|
|
|
|
interface MomentService {
|
|
suspend fun getMomentById(id: Int): MomentItem
|
|
suspend fun likeMoment(id: Int)
|
|
suspend fun getMoments(
|
|
pageNumber: Int,
|
|
author: Int? = null,
|
|
timelineId: Int? = null
|
|
): ListContainer<MomentItem>
|
|
}
|
|
|
|
|
|
class MomentPagingSource(
|
|
private val remoteDataSource: MomentRemoteDataSource,
|
|
private val author: Int? = null,
|
|
private val timelineId: Int? = null
|
|
) : PagingSource<Int, MomentItem>() {
|
|
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, MomentItem> {
|
|
return try {
|
|
val currentPage = params.key ?: 1
|
|
val moments = remoteDataSource.getMoments(
|
|
pageNumber = currentPage,
|
|
author = author,
|
|
timelineId = timelineId
|
|
)
|
|
|
|
LoadResult.Page(
|
|
data = moments.list,
|
|
prevKey = if (currentPage == 1) null else currentPage - 1,
|
|
nextKey = if (moments.list.isEmpty()) null else moments.page + 1
|
|
)
|
|
} catch (exception: IOException) {
|
|
return LoadResult.Error(exception)
|
|
}
|
|
}
|
|
|
|
override fun getRefreshKey(state: PagingState<Int, MomentItem>): Int? {
|
|
return state.anchorPosition
|
|
}
|
|
|
|
}
|
|
|
|
class MomentRemoteDataSource(
|
|
private val momentService: MomentService,
|
|
) {
|
|
suspend fun getMoments(
|
|
pageNumber: Int,
|
|
author: Int?,
|
|
timelineId: Int?
|
|
): ListContainer<MomentItem> {
|
|
return momentService.getMoments(pageNumber, author, timelineId)
|
|
}
|
|
}
|
|
|
|
|
|
class TestMomentServiceImpl() : MomentService {
|
|
val testMomentBackend = TestMomentBackend()
|
|
|
|
override suspend fun getMoments(
|
|
pageNumber: Int,
|
|
author: Int?,
|
|
timelineId: Int?
|
|
): ListContainer<MomentItem> {
|
|
return testMomentBackend.fetchMomentItems(pageNumber, author, timelineId)
|
|
}
|
|
|
|
override suspend fun getMomentById(id: Int): MomentItem {
|
|
return testMomentBackend.getMomentById(id)
|
|
}
|
|
|
|
|
|
override suspend fun likeMoment(id: Int) {
|
|
testMomentBackend.likeMoment(id)
|
|
}
|
|
|
|
}
|
|
|
|
class TestMomentBackend(
|
|
private val loadDelay: Long = 500,
|
|
) {
|
|
val DataBatchSize = 5
|
|
suspend fun fetchMomentItems(
|
|
pageNumber: Int,
|
|
author: Int? = null,
|
|
timelineId: Int?
|
|
): ListContainer<MomentItem> {
|
|
var rawList = TestDatabase.momentData
|
|
if (author != null) {
|
|
rawList = rawList.filter { it.authorId == author }
|
|
}
|
|
if (timelineId != null) {
|
|
val followIdList = TestDatabase.followList.filter {
|
|
it.first == timelineId
|
|
}.map { it.second }
|
|
rawList = rawList.filter { it.authorId in followIdList }
|
|
}
|
|
val from = (pageNumber - 1) * DataBatchSize
|
|
val to = (pageNumber) * DataBatchSize
|
|
if (from >= rawList.size) {
|
|
return ListContainer(
|
|
total = rawList.size,
|
|
page = pageNumber,
|
|
pageSize = DataBatchSize,
|
|
list = emptyList()
|
|
)
|
|
}
|
|
val currentSublist = rawList.subList(from, min(to, rawList.size))
|
|
// delay
|
|
kotlinx.coroutines.delay(loadDelay)
|
|
return ListContainer(
|
|
total = rawList.size,
|
|
page = pageNumber,
|
|
pageSize = DataBatchSize,
|
|
list = currentSublist
|
|
)
|
|
}
|
|
|
|
suspend fun getMomentById(id: Int): MomentItem {
|
|
return TestDatabase.momentData[id]
|
|
}
|
|
|
|
suspend fun likeMoment(id: Int) {
|
|
val oldMoment = TestDatabase.momentData.first {
|
|
it.id == id
|
|
}
|
|
val newMoment = oldMoment.copy(likeCount = oldMoment.likeCount + 1)
|
|
TestDatabase.updateMomentById(id, newMoment)
|
|
}
|
|
|
|
} |