我正在开发一个简单的 Android 应用程序用于教育目的。该应用程序使用 Room、Flow、Repository 和 ViewModel 在本地管理产品数据。
我正在 getProductById(id:Int) 方法内收集 ViewModel 中的流。
问题是:当使用 getProductById(id:Int) 检索产品时,一切正常。 但是当我删除这个产品时,出现错误:*“java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法”* 我猜流程仍在收集有关已删除产品的数据。并且,由于它不存在,因此会发生此错误。如何修复它?可以停流吗? 谢谢
ProductDAO使用Flow来获取数据:
@Dao
interface ProductDAO {
@Insert
suspend fun insert(productEntity: ProductEntity)
@Query("SELECT * FROM productentity ORDER BY name")
fun getAll(): Flow<List<ProductEntity>>
@Query("SELECT * FROM productEntity WHERE id=:id")
fun getProductById(id: Int): Flow<ProductEntity>
}
产品存储库。
class ProductRepository (private val productDAO: ProductDAO) {
suspend fun insert(product: ProductEntity){
contatoDAO.insert(product)
}
fun getAll(): Flow<List<Product>> {
return productDAO.getAll().map{list->list.map{it.toDoamin()}}
}
fun getProductById(id: Int): Flow<Product>{
return productDAO.getProductById(id).map{it.toDoamin()}
}
}
在我的 ViewModel 中我收集 Flow int getProductById() 方法
sealed class DetailProductState {
data object UpdateSuccess : DetalheState()
data object DeleteSuccess : DetalheState()
data class GetByIdSuccess(val p: Product) : DetailProductState()
data object ShowLoading : DetalheState()
}
class ProductViewModel(private val repository: ProductRepository) : ViewModel(){
private val _stateList = MutableStateFlow<DetailProductState>(DetailProductState.ShowLoading)
val stateList = _stateList.asStateFlow()
fun getProductById(id: Int) {
viewModelScope.launch {
repository.getProductById(id).collect{result->
_stateList.value= DetailProductState.GetByIdSuccess(result)
}
}
}
最后,在我的片段中
viewLifecycleOwner.lifecycleScope.launch{
viewModel.stateList.collect {
when (it) {
DetailProductState.DeleteSuccess -> {
Snackbar.make(
binding.root,
"Removed",
Snackbar.LENGTH_SHORT
).show()
findNavController().popBackStack()
}
is DetailProductState.GetByIdSuccess -> {
fillFields(it.p)
}
DetailProductState.ShowLoading -> {}
DetailProductState.UpdateSuccess -> {
Snackbar.make(
binding.root,
"Updated",
Snackbar.LENGTH_SHORT
).show()
findNavController().popBackStack()
}
}
}
}
我非常感谢您的帮助
每次数据库发生更改时,流程都会发出,并在查询没有结果时发出 null。因此将其定义为返回类型
Flow<ProductEntity?>
以防止其抛出NullPointerException。您可以选择如何响应收集器中的空值,或者在收集之前通过在流程上调用 filterNotNull()
来忽略它们。