首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Jetpack + Paging3 RemoteMediator传播错误

Jetpack + Paging3 RemoteMediator传播错误
EN

Stack Overflow用户
提问于 2021-12-01 16:28:32
回答 1查看 585关注 0票数 3

我正在尝试Jetpack,我已经创建了一个简单的应用程序来使用Ktor、Room、Hilt、Paging3和Material3来使用Jetpack。

我不明白如何传播在数据获取过程中捕获的任何最终错误。

AppDatabase.kt

代码语言:javascript
复制
@Database(
    entities = [
        SWCharacter::class
    ], version = 2, exportSchema = false
)
abstract class AppDatabase : RoomDatabase() {
    abstract fun people(): PeopleDao
}

PeopleService.kt

代码语言:javascript
复制
class PeopleService(private val httpClient: HttpClient) {
    suspend fun getPeople(page: Int?): SwapiResult<SWCharacter> {
        return httpClient.get(path = "api/people") {
            parameter("page", page)
        }
    }
}

RemoteMediator.kt

代码语言:javascript
复制
@ExperimentalPagingApi
class PeopleRemoteMediator @Inject constructor(private val database: AppDatabase, private val service: PeopleService) : RemoteMediator<Int, SWCharacter>() {
    private val dao: PeopleDao = database.people()

    override suspend fun initialize(): InitializeAction {
        return if (database.people().getCount() > 0) {
            InitializeAction.SKIP_INITIAL_REFRESH
        } else {
            InitializeAction.LAUNCH_INITIAL_REFRESH
        }
    }

    override suspend fun load(loadType: LoadType, state: PagingState<Int, SWCharacter>): MediatorResult {
        return try {
            val loadPage = when (loadType) {
                LoadType.REFRESH -> 1
                LoadType.PREPEND -> return MediatorResult.Success(endOfPaginationReached = true)
                LoadType.APPEND -> {
                    2
                }
            }

            val response = service.getPeople(page = loadPage)

            database.withTransaction {
                if (loadType == LoadType.REFRESH) {
                    dao.clearAll()
                }

                dao.insertAll(response.results)
            }

            MediatorResult.Success(endOfPaginationReached = response.next == null)

        } catch (e: IOException) {
            MediatorResult.Error(e)
        } catch (e: ResponseException) {
            MediatorResult.Error(e)
        }
    }
}

和PeopleRepository.kt

代码语言:javascript
复制
class PeopleRepository @Inject constructor(private val database: AppDatabase, private val service: PeopleService) {

    @ExperimentalPagingApi
    fun fetchPeople(): Flow<PagingData<SWCharacter>> {
        return Pager(
            PagingConfig(pageSize = 10, enablePlaceholders = false, prefetchDistance = 3),
            remoteMediator = PeopleRemoteMediator(database, service),
            pagingSourceFactory = { database.people().pagingSource() }
        ).flow
    }
}

我在ViewModel中使用了上述所有代码

代码语言:javascript
复制
@ExperimentalPagingApi
@HiltViewModel
class PeopleViewModel @Inject constructor(private val repo: PeopleRepository) : ViewModel() {
    private val _uiState = mutableStateOf<UIState>(UIState.Loading)
    val uiState: State<UIState>
        get() = _uiState

    init {
        viewModelScope.launch {
            try {
                val people = repo.fetchPeople()
                _uiState.value = UIState.Success(data = people)
            } catch (e: Exception) {
                _uiState.value = UIState.Error(message = e.message ?: "Error")
            }
        }
    }
}

sealed class UIState {
    object Loading : UIState()
    data class Success<T>(val data: T) : UIState()
    data class Error(val message: String) : UIState()
}

为了模拟错误,我将端点地址更改为:

代码语言:javascript
复制
return httpClient.get(path = "api/peoplethatnotexists")

错误在RemoteMediator中被正确捕获,但我不知道如何在视图模型中捕获它。

EN

回答 1

Stack Overflow用户

发布于 2022-09-16 18:20:05

为了侦听RemoteMediator错误,您可以向RecyclerView适配器添加一个LoadStateListener,如下所示:

代码语言:javascript
复制
mAdapter = MyAdapter(...).apply {
    addLoadStateListener { loadState ->
        val mediatorLoadState: LoadState? = loadState.mediator?.refresh

        if (mediatorLoadState is LoadState.Error) {
            // Herein you can implement your fallback 
            // as per mediatorLoadState.error 
        }
    }
}

同样,您可以通过要侦听的RemoteMediator的状态来更改loadState.mediator?.xxx。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70187840

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档