Jetpack Compose中painterResource崩溃,如何捕获异常避免应用崩溃?
问题描述
我的应用收到Crashlytics报告,部分用户遇到如下崩溃:
Fatal Exception: java.lang.IllegalArgumentException
Only VectorDrawables and rasterized asset types are supported ex. PNG, JPG
此前我偶尔遇到该Compose相关问题,但近期出现频率升高。该问题似乎是Compose的Bug,影响随机用户,且涉及的Drawable并不固定。
我希望能捕获painterResource的异常以避免应用崩溃,为此编写了如下Image Composable,但Composable中不允许使用try/catch:
@Composable fun AppImage( modifier: Modifier = Modifier, @DrawableRes resource: Int, colorFilter: ColorFilter? = null ) { Image( modifier = modifier, painter = painterResource(id = resource), contentDescription = null, colorFilter = colorFilter ) }
请问有什么可行的解决方案?
解决方案
方案一:用produceState异步加载并捕获异常
produceState支持在后台执行加载逻辑并处理异常,适合Compose中的状态管理场景:
@Composable fun AppImage( modifier: Modifier = Modifier, @DrawableRes resource: Int, colorFilter: ColorFilter? = null, placeholderPainter: Painter = painterResource(R.drawable.default_placeholder) // 替换为你的占位图资源 ) { val painterState = produceState<Painter?>(null, resource) { value = try { painterResource(resource) } catch (e: IllegalArgumentException) { // 捕获目标异常,返回占位图 placeholderPainter } catch (e: Exception) { // 兜底处理其他未知异常 placeholderPainter } } painterState.value?.let { painter -> Image( modifier = modifier, painter = painter, contentDescription = null, colorFilter = colorFilter ) } ?: run { // 加载失败且无占位图时,显示空白容器 Box(modifier = modifier) } }
方案二:将加载逻辑移到非Composable工具类
把Drawable加载逻辑放到非Composable环境中执行,捕获异常后再在Composable中用remember缓存结果:
// 非Composable工具类,处理Drawable加载逻辑 object PainterLoader { fun loadPainter(context: Context, @DrawableRes resId: Int): Painter? { return try { ContextCompat.getDrawable(context, resId)?.let { drawable -> DrawablePainter(drawable) } } catch (e: Exception) { null } } } // 你的自定义Image Composable @Composable fun AppImage( modifier: Modifier = Modifier, @DrawableRes resource: Int, colorFilter: ColorFilter? = null, placeholderPainter: Painter = painterResource(R.drawable.default_placeholder) ) { val context = LocalContext.current val painter = remember(resource) { PainterLoader.loadPainter(context, resource) ?: placeholderPainter } Image( modifier = modifier, painter = painter, contentDescription = null, colorFilter = colorFilter ) }
方案三:用Coil的AsyncImage替代(已集成Coil的项目)
如果项目已经使用Coil图片加载库,AsyncImage自带异常处理机制,支持加载本地资源,无需手动捕获异常:
@Composable fun AppImage( modifier: Modifier = Modifier, @DrawableRes resource: Int, colorFilter: ColorFilter? = null, placeholderPainter: Painter = painterResource(R.drawable.default_placeholder) ) { AsyncImage( model = ResourceDrawableId(resource), contentDescription = null, modifier = modifier, colorFilter = colorFilter, placeholder = placeholderPainter, error = placeholderPainter ) }
额外建议
- 排查资源文件:虽然问题随机,但可能存在部分VectorDrawable在特定设备上解析异常,检查资源XML是否符合规范,可为旧设备提供位图资源降级。
- 异常上报:捕获异常后,通过Crashlytics记录异常信息及对应的资源ID,帮助后续定位是否有特定资源的问题。
内容的提问来源于stack exchange,提问作者alfietap
相关产品推荐
相关产品推荐

