android - 协程在 Android 模拟器上工作,但不在真实设备上
问题描述
我一直在处理一个问题,试图将远程和本地数据源操作与协程同步,只有当我在真实设备中运行应用程序时才会发生这种问题,在 AS 模拟器中一切正常。我尝试遵循 Google 建议遵循相同结构和架构的所有指南、代码实验室和示例,结果始终相同:在模拟器上工作,在真实设备上失败。我尝试过使用两种不同操作系统版本的不同真实设备,但它们都失败了。
我想要实现的只是对 API 执行请求(通过改造)并将结果保存在数据库中。从真实设备执行并使用调试器时,似乎在某些时候执行了某些操作并且应用程序崩溃或什么也不做。我的代码:
改造服务:
@GET("product/{id}")
suspend fun getFoodByBarCode(@Path("id") id: String): FoodSchema
RemoteDataSource:任何时候都不会抛出任何异常
class FoodRemoteDataSource(private val foodService: FoodService) {
suspend fun getFoodByBarCode(code: String): Result<Food> = performRequest(RemoteMapper()) { foodService.getFoodByBarCode(code) }
private suspend fun <T, R> performRequest(modelMapper: BaseMapper<T, R>, call: suspend () -> T): Result<R> {
try {
val response = call()
if(response != null) return Result.Success(modelMapper.execute(response)) else throw Exception("The server response is null")
} catch (e: Exception) {
throw e
}
}
数据库 DAO
@Query("SELECT * FROM food")
fun observeAllFood(): LiveData<List<Food>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertFood(food: Food)
本地数据源
class FoodLocalDataSource(
private val foodDao: FoodDao,
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO) : FoodDataSource {
override fun observeAllFood(): LiveData<Result<List<Food>>> {
return foodDao.observeAllFood().map { Success(it) }
}
override suspend fun saveFood(food: Food) =
withContext(ioDispatcher) { foodDao.insertFood(food) }
存储库
class FoodRepository(private val localDataSource: FoodLocalDataSource,
private val remoteDataSource: FoodRemoteDataSource) : FoodDataSource {
override fun observeAllFood(): LiveData<Result<List<Food>>> {
return localDataSource.observeAllFood()
}
suspend fun fetchFoodByBarCode(barCode: String) {
val result = remoteDataSource.getFoodByBarCode(barCode)
if(result.succeeded) saveFood((result as Result.Success).data)
}
override suspend fun saveFood(food: Food) {
localDataSource.saveFood(food)
}
}
视图模型
class FoodListViewModel(private val foodRepository: FoodRepository) : BaseViewModel() {
private val _foodList = requestFoodList()
val foodList: LiveData<List<Food>> = _foodList
private fun requestFoodList(): LiveData<List<Food>> {
showLoading()
return foodRepository.observeAllFood().distinctUntilChanged()
.switchMap { extractResult(it) }
}
fun fetchFoodByBarCode(barCode: String) {
launchDataLoad { foodRepository.fetchFoodByBarCode(barCode) }
}
private fun <T : Any> extractResult(
result: Result<T>,
autoHideLoading: Boolean = true
): LiveData<T> {
val mutableLiveData = MutableLiveData<T>().apply { value = null }
if (autoHideLoading) hideLoading()
when (result) {
is Result.Success -> {
mutableLiveData.value = result.data!!
}
is Result.Error -> {
_error.value = true
mutableLiveData.value = null
}
}
return mutableLiveData
}
}
我的活动只是观察foodList
填充 RecyclerView 并在fetchFoodByBarCode()
单击按钮时调用。
知道有什么问题吗?提前致谢!
解决方案
推荐阅读
- docker-compose - 超级账本结构:docker-compose orderer 出口 2
- paperjs - 将点添加到 Path.Circle 第一个点是 0,0?
- linux - 如何使用 systemd 和 aplay 播放启动声音?
- python - np.isin() 忽略数组的一些条目
- gridview - 在现代工具包 extjs 中,单击即可编辑网格单元
- python - sqlalchemy 标量子查询转换
- database - 最高范式
- amazon-web-services - 通过外部编辑器 (AWS CLI) 访问 AWS,虽然授权但授权错误
- sql - Hive - 以分钟计算字符串类型时间戳差异
- c# - 处理 IIS 托管的 Web 服务启动失败