You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 10:44:55