Android中ViewModel获取单条Room数据返回null及Image加载问题求助
问题解决:Room单条数据加载失效与Compose Image组件适配
一、修复单条Recipe数据加载问题
1. 调整ViewModel的LiveData实现
原ViewModel中eventSingle使用lateinit导致初始化时机不可控,替换为MutableLiveData统一管理数据状态:
class RecipeViewModel(application: Application): AndroidViewModel(application) { val readAllData: LiveData<List<RecipeModel>> private val repository: RecipeRepository private val _eventSingle = MutableLiveData<RecipeModel?>() val eventSingle: LiveData<RecipeModel?> = _eventSingle init { val recipeDAO = RecipeDatabase.getDatabase(application).recipeDao() repository = RecipeRepository(recipeDAO) readAllData = repository.readAllData } fun getSingle(recipeId: String) { val liveData = repository.loadSingle(recipeId) liveData.observeForever { recipe -> _eventSingle.value = recipe liveData.removeObserver { } // 数据获取后移除观察者,避免内存泄漏 } } }
2. 修正Composable的数据收集逻辑
在RecipeScreen中正确处理LiveData的状态,仅在数据非空时渲染内容:
@Composable fun RecipeScreen(navController: NavHostController, recipeViewModel: RecipeViewModel, recipeID: Int) { println("RECIPE ID" + recipeID.toString()) recipeViewModel.getSingle(recipeID.toString()) val available by recipeViewModel.eventSingle.observeAsState(null) available?.let { recipe -> // 渲染完整食谱内容 Hero(recipe) // 其他食谱详情组件 } ?: run { // 数据加载中或为空时显示占位 Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { CircularProgressIndicator() } } }
3. 修复NavHost的参数判断逻辑
原判断recipeID != ""会遗漏null情况,改为安全的空值处理:
composable(route = Recipe.route) { backStackEntry -> val recipeID = backStackEntry.arguments?.getString("recipeID") recipeID?.let { id -> RecipeScreen(navController, recipeViewModel, id.toInt()) } ?: run { Text(text = "无效的食谱ID", modifier = Modifier.fillMaxSize().wrapContentSize()) } }
二、修复Image组件加载问题
1. 增加Drawable存在性判断
当图片资源不存在时,显示占位组件而非直接崩溃:
@Composable fun Hero(recipePreview: RecipeModel) { val context = LocalContext.current val imageName = recipePreview.image.replace(".jpg", "") val drawableId = remember(imageName) { context.resources.getIdentifier( imageName, "drawable", context.packageName ) } Box(Modifier.height(280.dp)) { if (drawableId != 0) { Image( painter = painterResource(id = drawableId), contentDescription = recipePreview.title, modifier = Modifier .fillMaxWidth() .fillMaxHeight(), contentScale = ContentScale.FillBounds, ) } else { // 图片资源不存在时显示占位背景 Box( modifier = Modifier .fillMaxSize() .background(Color.LightGray), contentAlignment = Alignment.Center ) { Text(text = "图片未找到", color = Color.DarkGray) } } } }
2. 确保Hero组件仅在数据非空时调用
通过available?.let { }的判断逻辑,保证传入Hero的recipePreview永远非空,从根源避免空指针异常。
内容的提问来源于stack exchange,提问作者Soufiane Sabiri
相关产品推荐
相关产品推荐

