|
|
@@ -3,11 +3,14 @@ package com.grkj.ui_base.skin
|
|
|
import android.app.Application
|
|
|
import android.net.Uri
|
|
|
import android.widget.ImageView
|
|
|
+import androidx.annotation.DrawableRes
|
|
|
import androidx.documentfile.provider.DocumentFile
|
|
|
import coil.ImageLoader
|
|
|
import coil.decode.SvgDecoder
|
|
|
+import coil.imageLoader
|
|
|
import coil.request.CachePolicy
|
|
|
import coil.request.ImageRequest
|
|
|
+import com.grkj.ui_base.R
|
|
|
import com.sik.sikcore.SIKCore
|
|
|
import java.io.File
|
|
|
|
|
|
@@ -90,33 +93,40 @@ object SkinIcons {
|
|
|
defaultAssetsBase: String,
|
|
|
logicalPath: String,
|
|
|
app: Application = SIKCore.getApplication(),
|
|
|
- placeholderRes: Int? = null
|
|
|
+ @DrawableRes placeholderRes: Int? = null
|
|
|
) {
|
|
|
- // 1) 决定使用哪个基准
|
|
|
+ // 1) 主题/路径
|
|
|
val effectiveTheme = theme ?: ThemeSpec(
|
|
|
name = "default",
|
|
|
- base = IconBase.Assets(defaultAssetsBase) // e.g. "themes/Default/icons"
|
|
|
+ base = IconBase.Assets(defaultAssetsBase)
|
|
|
)
|
|
|
-
|
|
|
- // 2) 解析 Uri(assets 会直接得到 file:///android_asset/...)
|
|
|
val uri = resolveIconUri(app, effectiveTheme, logicalPath)
|
|
|
|
|
|
- // 3) Coil 加载(支持 SVG)
|
|
|
- val req = ImageRequest.Builder(imageView.context)
|
|
|
- .data(uri ?: placeholderRes)
|
|
|
- .apply {
|
|
|
- if (placeholderRes != null) placeholder(placeholderRes)
|
|
|
- error(placeholderRes ?: 0) // 使用错误占位图
|
|
|
- // 通过配置内存缓存,避免频繁加载相同的图像
|
|
|
- memoryCachePolicy(CachePolicy.ENABLED)
|
|
|
- }
|
|
|
- .target(imageView)
|
|
|
- .allowHardware(false) // 禁止硬件加速,防止闪烁
|
|
|
- .build()
|
|
|
+ // 2) 去重(同一资源就别重复加载)
|
|
|
+ val key = "${effectiveTheme.name}::$logicalPath"
|
|
|
+ if (imageView.getTag(R.id.tag_icon_key) == key) return
|
|
|
+ imageView.setTag(R.id.tag_icon_key, key)
|
|
|
|
|
|
- svgLoader(imageView).enqueue(req)
|
|
|
- }
|
|
|
+ // 3) 仅 SVG 关闭硬件位图,其他走硬件位图减轻 Java 堆压力(更抗 OOM)
|
|
|
+ val isSvg = uri?.toString()?.endsWith(".svg", ignoreCase = true) == true
|
|
|
|
|
|
+ // 4) 构建请求:占位=当前图(无视觉闪烁);使用 ViewTarget 以便自动取消旧请求
|
|
|
+ val builder = ImageRequest.Builder(imageView.context)
|
|
|
+ .data(uri ?: placeholderRes) // 没资源就用占位
|
|
|
+ .memoryCacheKey(key) // 跨列表项复用结果
|
|
|
+ .crossfade(false) // 彻底关过渡
|
|
|
+ .allowHardware(!isSvg) // 只有 SVG 才禁硬件
|
|
|
+ .diskCachePolicy(CachePolicy.DISABLED) // assets 本地文件,不需要磁盘缓存
|
|
|
+ .placeholder(
|
|
|
+ placeholderRes?.let { imageView.context.getDrawable(it) }
|
|
|
+ ?: imageView.drawable // 无占位 -> 保持现图,不清空 => 不闪
|
|
|
+ )
|
|
|
+ .target(imageView) // 关键:回到 ViewTarget,自动取消上一个请求
|
|
|
+
|
|
|
+ if (placeholderRes != null) builder.error(placeholderRes)
|
|
|
+
|
|
|
+ imageView.context.imageLoader.enqueue(builder.build())
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|