Jetpack Compose中mutableStateOf列表加载Composable崩溃问题解决
Jetpack Compose加载API数据渲染Composable崩溃解决
崩溃原因
从崩溃日志可直接定位核心问题:
java.lang.NullPointerException: Parameter specified as non-null is null: method com.brickbox.BricksBackEndKt.Brick, parameter brickNumber
传给Brick Composable的brickNumber参数为null,但该参数被定义为非空类型,触发空指针异常。原代码中使用legoPart.part.partNum作为该参数的值,说明API返回的部分数据里partNum字段为null,无法满足Brick组件的参数要求。
同时原代码存在两处不规范实现:
- 使用
GlobalScope启动协程:未绑定Composable生命周期,存在内存泄漏风险 - 使用
mutableStateOf(listOf<LegoPart>()):通过替换整个列表触发重组,效率低于直接操作可观察列表
解决代码
val mutableBricksList = remember { mutableStateListOf<LegoPart>() } val scope = rememberCoroutineScope() Button(onClick = { scope.launch { val fetchedLegoBricks = fetchLegoSetBricks("https://rebrickable.com/api/v3/lego/sets/${setNumber}/parts/?key=${BuildConfig.API_KEY}") if (fetchedLegoBricks != null) { fetchedLegoBricks.forEach { legoPart -> mutableBricksList.add(legoPart) } } } }) { Text("Load Bricks") } mutableBricksList.forEach { legoPart -> Brick( brickNumber = legoPart.id.toString(), brickName = legoPart.part.name, imageURL = legoPart.part.partImgUrl ) println(legoPart.part.name) }
关键改动说明
- 替换状态容器:用
mutableStateListOf<LegoPart>()替代mutableStateOf(listOf<LegoPart>()),可观察列表的元素增删操作会自动触发Composable重组,无需替换整个列表。 - 使用生命周期绑定的协程作用域:
rememberCoroutineScope()创建与当前Composable生命周期绑定的协程作用域,避免GlobalScope带来的内存泄漏问题。 - 修复空指针参数:将
brickNumber的取值从可能为null的legoPart.part.partNum改为legoPart.id.toString(),确保传入非空值,满足Brick组件的参数要求。 - 简化线程切换:
fetchLegoSetBricks内部已通过withContext(Dispatchers.IO)处理IO操作,外部协程无需额外指定调度器,默认在主线程执行后续列表操作,符合Compose状态操作的线程要求。
补充:API数据解析注意事项
使用Gson解析时,若API返回字段可能为null,需确保数据类对应字段定义为可空类型(如var partNum: String? = null),避免解析时出现隐性空值问题。
内容的提问来源于stack exchange,提问作者George Clensy
相关产品推荐
相关产品推荐

