androidx.paging.PagingData转换方法内异常捕获问题咨询
解决PagingData转换为UIModel过程中的异常崩溃问题
问题背景
现有一段将分页数据模型转换为UIModel的代码,存在两个潜在崩溃点:deserialize方法执行时、调用getOrThrow()时。尝试在流末尾添加.catch{}或使用普通try-catch均无效,原因是PagingData的转换操作在其他线程执行。
原代码如下:
pagingData .map { cachedData -> deserialize(cachedData) } .filter { it.isSuccess } .map { it -> mapToUiModel(it.getOrThrow()) }
解决方案
1. 用runCatching包裹所有可能抛异常的转换步骤
将每个可能抛出异常的操作(deserialize、mapToUiModel)用runCatching包裹,将异常转换为Result类型,避免异常直接抛出到Paging流中,同时通过filter过滤掉失败的结果:
pagingData // 包裹deserialize,捕获反序列化异常 .map { cachedData -> runCatching { deserialize(cachedData) } } // 过滤掉反序列化失败的项 .filter { it.isSuccess } // 安全获取反序列化结果(已过滤isSuccess,getOrThrow不会崩溃) .map { it.getOrThrow() } // 包裹mapToUiModel,捕获UI模型转换异常 .map { dataModel -> runCatching { mapToUiModel(dataModel) } } // 过滤掉UI模型转换失败的项 .filter { it.isSuccess } // 安全获取最终UIModel .map { it.getOrThrow() }
2. 手动try-catch处理异常(适合无法使用Result的场景)
如果无法依赖Result类型,可在每个map步骤中手动添加try-catch,捕获异常后标记失败状态,再过滤掉错误项:
pagingData .map { cachedData -> try { // 成功则返回标记+结果 Pair(true, deserialize(cachedData)) } catch (e: Exception) { // 捕获异常并记录日志(可选) // Log.e("PagingConversion", "Deserialize failed", e) Pair(false, null) } } // 过滤反序列化失败的项 .filter { it.first } .map { it.second!! } .map { dataModel -> try { Pair(true, mapToUiModel(dataModel)) } catch (e: Exception) { // Log.e("PagingConversion", "Map to UIModel failed", e) Pair(false, null) } } // 过滤UI模型转换失败的项 .filter { it.first } .map { it.second!! }
3. 关键说明
PagingData的转换操作(map、filter等)运行在Paging库内部调度器上,流的异常会直接传递到collect环节,因此必须在每个可能抛出异常的转换步骤中就地处理,而非在流末尾统一捕获。若mapToUiModel逻辑稳定不会抛异常,可省略对应环节的捕获,但建议保留逻辑以应对后续代码变更。
内容的提问来源于stack exchange,提问作者Ferencz Andras
相关产品推荐
相关产品推荐

