我正在尝试Coroutine
在我的内部启动一个PagingSource
,以查看我的分页源已经尝试获取我的数据多长时间。我在这里遇到的唯一问题是Coroutine
,即使我停止了shopPagingWatcher Flow
. 正因为如此,它throws IOException("No Intenet Exception)
即使不应该。
我正在启动一个Coroutine
因为看状态不应该阻塞我的主流paging source
寻呼源
class ShopRemoteMediator @Inject constructor(
private val db: FirebaseFirestore,
private val shopPagingWatcher: ShopPagingWatcher,
) : PagingSource<QuerySnapshot, Product>() {
@InternalCoroutinesApi
override suspend fun load(params: LoadParams<QuerySnapshot>): LoadResult<QuerySnapshot, Product> {
return try {
// Launch Async Coroutine, Observe State, throw IO Exception when not loaded within 5 seconds
shopPagingWatcher.start()
CoroutineScope(Dispatchers.IO).launch {
shopPagingWatcher.observeMaxTimeReached().collect { maxTimeReached ->
if (maxTimeReached) {
Timber.d("Mediator failed")
throw IOException("No Internet Exception")
}
}
}
val currentPage = params.key ?: db.collection(FIREBASE_PRODUCTS)
.limit(SHOP_LIST_LIMIT)
.get()
.await()
val lastDocumentSnapShot = currentPage.documents[currentPage.size() - 1]
val nextPage = db.collection(FIREBASE_PRODUCTS)
.limit(SHOP_LIST_LIMIT)
.startAfter(lastDocumentSnapShot)
.get()
.await()
// When PagingSource is here, it successfully loaded currentPage and nextPage, therefore stop Watcher
Timber.d("Mediator Sucessfull")
shopPagingWatcher.stop()
LoadResult.Page(
data = currentPage.toObjects(),
prevKey = null,
nextKey = nextPage
)
} catch (e: Exception) {
// IOException should be caught here, but it is not! The app crashed instead!
Timber.d("Mediator Exception ist $e")
LoadResult.Error(e)
}
}
}
ShopPagingWatcher
@Singleton
class ShopPagingWatcher @Inject constructor() : Workwatcher()
抽象工作观察者
abstract class Workwatcher {
private companion object {
private val dispatcher = Dispatchers.IO
private var timeStamp by Delegates.notNull<Long>()
private var running = false
private var manuallyStopped = false
private var finished = false
private const val maxTime: Long = 5000000000L
}
// Push the current timestamp, set running to true
// I don't know if it is necessary to use "synchronized"
@InternalCoroutinesApi
fun start() = synchronized(dispatcher) {
timeStamp = System.nanoTime()
running = true
manuallyStopped = false
finished = false
}
// Manually stop the WorkerHelper
// I don't know if it is necessary to use "synchronized"
@InternalCoroutinesApi
fun stop() = synchronized(dispatcher) {
running = false
manuallyStopped = true
finished = true
Timber.d("Mediator stopped")
}
// Function that observes the time
fun observeMaxTimeReached(): Flow<Boolean> = flow {
// Check if maxTime is not passed with → (System.nanoTime() - timeStamp) <= maxTime
while (running && !finished && !manuallyStopped && (System.nanoTime() - timeStamp) <= maxTime) {
emit(false)
Timber.d("Currenttime is smaller, everything fine")
}
// This will be executed only when the Worker is running longer than maxTime
if (!manuallyStopped && !finished) {
Timber.d("Currenttime bigger, yikes. Stop worker")
emit(true)
running = false
finished = true
return@flow
} else if (finished || manuallyStopped) {
return@flow
}
}.flowOn(dispatcher)
}
我应该如何改变我的Coroutine
内心PagingSource
以实现我的目标?Timber.d("Mediator stopped)
被调用。
我感谢每一个帮助,谢谢。