从ImageView获取Drawable返回Null,无法提取图片主色调问题排查
问题原因及解决办法
核心问题
你遇到的Null或类型转换失败问题,本质是两个关键原因:
- Glide加载是异步操作:调用
loadInto后立刻执行getDominantColor,此时网络图片还没加载完成,ImageView里的drawable仍是默认的@drawable/icon_default(如果这个资源是矢量图,那它是VectorDrawable而非BitmapDrawable,强转必然失败)。 - 强制类型转换不安全:直接把
image.drawable强转为BitmapDrawable,一旦drawable是矢量图、ShapeDrawable等非BitmapDrawable类型,就会抛出异常,导致无法获取Bitmap。
推荐解决方案:用Glide的CustomTarget直接获取Bitmap
通过Glide的CustomTarget获取加载完成的Bitmap,既可以设置到ImageView,又能直接用Bitmap生成Palette,完全规避异步和类型转换问题:
1. 替换原有的loadInto方法
fun loadImageAndExtractDominantColor(url: String, imageView: ImageView) { Glide.with(imageView) .asBitmap() // 明确要求加载为Bitmap格式 .load(url) .placeholder(R.drawable.icon_default) // 设置加载占位图 .error(R.drawable.icon_default) // 设置加载失败图 .into(object : CustomTarget<Bitmap>() { override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) { // 将加载好的Bitmap设置到ImageView imageView.setImageBitmap(resource) // 生成Palette并提取主色调 Palette.from(resource).generate { palette -> val dominantColor = palette?.getDominantColor(0x000000) ?: 0x000000 setGradientColor(dominantColor) } } override fun onLoadCleared(placeholder: Drawable?) { // 加载任务被清除时,设置占位图 placeholder?.let { imageView.setImageDrawable(it) } } }) }
2. 修改collect中的调用逻辑
viewLifecycleOwner.lifecycleScope.launchWhenStarted { viewOutput.iconFlow.collect { photoUrl -> photoUrl?.let { // 直接调用新方法,无需单独执行getDominantColor loadImageAndExtractDominantColor(it, binding.ivIcon) } } }
额外注意事项
- 修正变量名:你代码里的
binding.Icon应该是binding.ivIcon(XML中定义的id是ivIcon),否则会出现视图找不到的问题。 - 兼容非BitmapDrawable:如果需要兼容矢量图等资源,
asBitmap()会让Glide自动将矢量图转为Bitmap加载,无需额外处理类型转换。
内容的提问来源于stack exchange,提问作者Sergey1996
相关产品推荐
相关产品推荐

