在 Picasso 中应用变换时,原始图像的缓存未被重用
Cache of Original Image Is Not Reused When Applying Transform in Picasso
我正在尝试使用 Picasso 在原始位图和转换后的位图之间切换。
问题是第一次加载原始图像时它似乎被缓存了,但是当我加载转换后的图像时它似乎再次重新加载图像并且不使用缓存。相同的 url 用于获取图像。它只发生在原始和转换的第一次,然后使用缓存。
我期望 Picasso 应该自动重用已兑现的原始图像以应用转换并立即重新加载它。也许我错过了什么。
这里是图片加载的代码。
private fun loadOriginalImage(i: Product, productImage: ImageView) {
Picasso.get().load(getProductUrl(i.id)).placeholder(R.color.light_grey)
.error(R.color.light_grey).fit().centerCrop().into(productImage)
}
private fun loadGreyedImage(i: Product, productImage: ImageView) {
Picasso.get().load(getProductUrl(i.id)).placeholder(R.color.light_grey)
.error(R.color.light_grey).fit().centerCrop().transform(GrayScaleTransform()).into(productImage)
}
毕加索版本implementation 'com.squareup.picasso:picasso:2.71828'
是内存缓存还是磁盘缓存?
您如何验证缓存确实未被使用?
这里有一些选项(考虑到 MemoryPolicy 和 NetworkPolicy 没有被修改,你也没有替换标准的 okHTTP3 客户端):
- 图像在这两个调用之间被推出内存缓存(缓存太小,无效调用等)
- 磁盘缓存由 HTTP 客户端控制,与 Picasso 无关,因此不正确设置 http headers 可能会导致这种情况(但在那种情况下,原始图像应该已经从内存缓存中删除)
打开指示器和日志记录可以提供有关正在发生的事情的更多信息:
Picasso
.with(context)
.setIndicatorsEnabled(true)
.setLoggingEnabled(true)
此外,如果有可能只执行这两个调用,您可以执行它们并从内存缓存中获取快照数据以检查其大小、命中和未命中等:
StatsSnapshot stats = Picasso.with(context).getSnapshot();
Log.d("stats", stats.toString());
这可能会提供更多调试信息以供考虑,例如是否恰好有两次对缓存的调用,是否有未命中等
编辑:您的转换中是否正确实现了 key() 函数?
启用日志后,我验证了原始图像确实被缓存了,正如@Sputnik 所说,问题似乎是由从原始图像缓存创建转换位图的延迟引起的。
但是 pre-caching 转换图像的解决方案并不是最好的 imo。首先,有很多图像,只有当用户点击回收器中的图像时才需要灰度图像。它可能永远不会发生,但我们已经缓存了双倍大小的图像以防万一。
因此,在使用 Picasso 并记录后,对我有用的解决方案是使用原始图像作为占位符。
所以而不是
Picasso.get().load(getProductUrl(i.id)).placeholder(R.color.light_grey)
.error(R.color.light_grey).fit().centerCrop().transform(GrayScaleTransform()).into(productImage)
我做到了
Picasso.get().load(getProductUrl(i.id)).placeholder(productImage.drawable)
.error(R.color.light_grey).fit().centerCrop().transform(GrayScaleTransform()).into(productImage)
这样我的占位符就是原始图像,它使过渡平滑,并通过缓存所有转换后的图像消除了潜在的开销。
我正在尝试使用 Picasso 在原始位图和转换后的位图之间切换。 问题是第一次加载原始图像时它似乎被缓存了,但是当我加载转换后的图像时它似乎再次重新加载图像并且不使用缓存。相同的 url 用于获取图像。它只发生在原始和转换的第一次,然后使用缓存。
我期望 Picasso 应该自动重用已兑现的原始图像以应用转换并立即重新加载它。也许我错过了什么。
这里是图片加载的代码。
private fun loadOriginalImage(i: Product, productImage: ImageView) {
Picasso.get().load(getProductUrl(i.id)).placeholder(R.color.light_grey)
.error(R.color.light_grey).fit().centerCrop().into(productImage)
}
private fun loadGreyedImage(i: Product, productImage: ImageView) {
Picasso.get().load(getProductUrl(i.id)).placeholder(R.color.light_grey)
.error(R.color.light_grey).fit().centerCrop().transform(GrayScaleTransform()).into(productImage)
}
毕加索版本implementation 'com.squareup.picasso:picasso:2.71828'
是内存缓存还是磁盘缓存? 您如何验证缓存确实未被使用?
这里有一些选项(考虑到 MemoryPolicy 和 NetworkPolicy 没有被修改,你也没有替换标准的 okHTTP3 客户端):
- 图像在这两个调用之间被推出内存缓存(缓存太小,无效调用等)
- 磁盘缓存由 HTTP 客户端控制,与 Picasso 无关,因此不正确设置 http headers 可能会导致这种情况(但在那种情况下,原始图像应该已经从内存缓存中删除)
打开指示器和日志记录可以提供有关正在发生的事情的更多信息:
Picasso
.with(context)
.setIndicatorsEnabled(true)
.setLoggingEnabled(true)
此外,如果有可能只执行这两个调用,您可以执行它们并从内存缓存中获取快照数据以检查其大小、命中和未命中等:
StatsSnapshot stats = Picasso.with(context).getSnapshot();
Log.d("stats", stats.toString());
这可能会提供更多调试信息以供考虑,例如是否恰好有两次对缓存的调用,是否有未命中等
编辑:您的转换中是否正确实现了 key() 函数?
启用日志后,我验证了原始图像确实被缓存了,正如@Sputnik 所说,问题似乎是由从原始图像缓存创建转换位图的延迟引起的。
但是 pre-caching 转换图像的解决方案并不是最好的 imo。首先,有很多图像,只有当用户点击回收器中的图像时才需要灰度图像。它可能永远不会发生,但我们已经缓存了双倍大小的图像以防万一。
因此,在使用 Picasso 并记录后,对我有用的解决方案是使用原始图像作为占位符。
所以而不是
Picasso.get().load(getProductUrl(i.id)).placeholder(R.color.light_grey)
.error(R.color.light_grey).fit().centerCrop().transform(GrayScaleTransform()).into(productImage)
我做到了
Picasso.get().load(getProductUrl(i.id)).placeholder(productImage.drawable)
.error(R.color.light_grey).fit().centerCrop().transform(GrayScaleTransform()).into(productImage)
这样我的占位符就是原始图像,它使过渡平滑,并通过缓存所有转换后的图像消除了潜在的开销。