当前位置: 首页 > 知识库问答 >
问题:

Glide,使用“CustomTarget()”是否比使用“CustomViewTarget”更好地减少内存使用?

秦英发
2023-03-14

在android应用程序中使用Glide v4。用例是有一个活动在backback中有几个片段。每个片段将从远程加载一到不到十个图像。

具有用于将图像加载到ImageView的kotlin扩展:

fun ImageView.loadImg(
    imageUrl: String,
    diskCacheStrategy: DiskCacheStrategy = DiskCacheStrategy.AUTOMATIC,
    skipMemoryCache: Boolean = true,
    roundingRadius: Int = 0,
    target: Target<Drawable>? = null,
    requestOptions: RequestOptions = RequestOptions(),
    decodeFormat: DecodeFormat = DecodeFormat.PREFER_RGB_565 
) {
    requestOptions
        .diskCacheStrategy(diskCacheStrategy)
        .format(decodeFormat)
        .apply {
            if (roundingRadius > 0) {
                transform(CenterCrop(), RoundedCorners(roundingRadius))
            }
        }

        Glide.with(this.context)
            .load(imageUrl)
            .apply(requestOptions)
            .skipMemoryCache(skipMemoryCache)
            .apply {
                if (target == null) {
                    into(this@loadImg)
                } else {
                    into(target)
                }
            }
}

片段中的典型调用如下:

imageView.loadImg(
            imageUrl = imageUrl,
            roundingRadius = imageRoundingRadius,
            target = object : CustomViewTarget<ImageView, Drawable>(imageView) {
                override fun onLoadFailed(errorDrawable: Drawable?) {
                   imageView.setImageDrawable(null)
                    visibility = View.GONE
                }
                override fun onResourceCleared(placeholder: Drawable?) {
                    imageView.setImageDrawable(null)
                    visibility = View.GONE
                }
                override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
                    imageView.setImageDrawable(resource)
                    visibility = View.VISIBLE
                }
            }
        )

问题是,每当看到一个片段并将其添加到Backback时,探查器中的图形内存就会增加50 mg。除了片段中的图像之外,没有太多其他数据。如果注释掉,加载的图像似乎减少了很多。

不确定此处的代码loadImage()是否正确?注意,它在Glide.with(this.context)中使用了ImageView的上下文,这是活动。这是个问题吗?Glide.with(this.context)和Glide有什么区别。有(碎片)?什么时候是清除目标的最佳时间:滑翔。用(碎片)。清除(目标)?

注意,有一个CustomTarget(),如果它可以接受图像大小,那么使用它是否有助于减少内存使用?

代码与目标类似:target

fun ImageView.loadImgAsBitmap(
    imageUrl: String,
    diskCacheStrategy: DiskCacheStrategy = DiskCacheStrategy.AUTOMATIC,
    skipMemoryCache: Boolean = true,
    roundingRadius: Int = 0,
    target: Target<Bitmap>? = null,
    requestOptions: RequestOptions = RequestOptions(),
    decodeFormat: DecodeFormat = DecodeFormat.PREFER_RGB_565 
) {
    requestOptions
            .diskCacheStrategy(diskCacheStrategy)
            .format(decodeFormat)
            .apply {
                if (roundingRadius > 0) {
                    transform(CenterCrop(), RoundedCorners(roundingRadius))
                }
            }

        Glide.with(this.context)
                .asBitmap()
                .load(imageUrl)
                .apply(requestOptions)
                .skipMemoryCache(skipMemoryCache)
                .apply {
                    if (target == null) {
                        into(this@loadImgAsBitmap)
                    } else {
                        into(target)
                    }
                }
}

用法为:

imageView.loadImgAsBitmap(imageUrl,
            target = object : CustomTarget<Bitmap>() {
                override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
                    if (resource.height < IMAGE_MIN_SIZE) {// it could check the bitmap size and make use of it
                        imageView.visibility = View.GONE
                        textView.visibility = View.VISIBLE
                    } else {
                        imageView.setImageBitmap(resource)
                    }
                }
                override fun onLoadCleared(placeholder: Drawable?) {
                    imageView.setImageDrawable(null)
                }
            })

这一个至少更好地提供位图大小,以便用户界面可以利用它。

问题是使用CustomTarget是否更好


共有1个答案

周兴朝
2023-03-14

可能回答晚了。我一直在研究使用Glide v4优化图像负载,并来到了这篇好文章。作者提供了详细的解释和建议的解决方案,其中一个示例与问题中提出的用例完全相似。

总之,不是每次视图离开屏幕时都调用Glide.with(上下文). Clear(ImageView)(移动到反向堆栈),作者建议使用:

  • RGB_565位图格式(Glide v4默认使用ARGB_8888),条件是图像不包含透明度和明显的梯度斑点。它可以减少高达50%的内存消耗。
  • CustomViewTarget,或CustomTarget,其大小传递给其构造函数或调用覆盖以指定所需的位图尺寸,因为CustomTarget在未指定尺寸时倾向于加载原始图像尺寸。而前者,CustomViewTarget,当至少有一个维度已知时,始终根据视图维度加载图像。
 类似资料:
  • 问题内容: 我正在编写独立于操作系统的无锁队列,到目前为止,它工作得很好,但是内存管理方面的问题很小。我不确定它的gcc问题还是我的。问题:将元素添加到列表时,内存增加,但是从列表中删除元素(free(elementPointer);)时,内存使用率没有变化。 但是,当我使用pthreads时,N个生产者和M个消费者的 内存使用量始终约为10mb(当尝试添加和删除〜10kk元素时),因此看起来自由

  • 实际上,我的问题和这个问题非常相似,但这篇文章只关注C#。最近我读到一篇文章,说java会将一些短类型(如short)提升到内存中的4字节,即使有些位不被使用,所以它不能减少使用。(是真的吗?) 所以我的问题是语言,特别是C、C++和java(正如Manish在这篇文章中谈到java时所说),如何处理小型数据类型的内存分配。参考资料或任何方法来找出它是首选的。谢谢

  • 问题内容: 我正在尝试将几个文件加载到内存中。这些文件具有以下3种格式之一: 字符串TAB int 字符串TAB浮动 int TAB浮点数。 的确,它们是ngram静态文件,以防解决方案的出现。例如: 目前,我正在执行的伪代码是 令我惊讶的是,尽管磁盘中文件的总大小约为21 mb,但是将其加载到内存中时,该过程将占用120-180 mb的内存!(整个python应用程序不会将其他任何数据加载到内存

  • 我正在使用spring boot开发客户端应用程序。在运行spring boot应用程序(使用完全可执行的jar)时,x64服务器的内存占用约为190M,x86服务器的内存占用约为110M。 我的jvm选项是(-xmx64m-xms64m-xx:maxpermsize=64m-server),为什么在x64服务器中,内存占用这么大?如何将内存使用量降低到150M以下? 多谢了。

  • 我有一个Java程序可以在Solaris 10 X86上运行,具有2GB物理内存和2GB交换。 该程序在64位Linux中运行良好,仅消耗约450MB内存。 然而,当它在Solaris中运行时,它总是报告OutOfMemoryError,我注意到在错误发生之前,它正试图使用 那么为什么JVM会尝试使用那么多虚拟内存呢?有没有办法告诉JVM不要使用那么多虚拟内存? 谢谢你。 编辑: 谢谢大家的意见!

  • 问题内容: 我将Selenium和Firefox Webdriver与python配合使用,以从网站中抓取数据。 但是在代码中,我需要访问该网站超过10k次,并且这样做要消耗大量RAM。 通常,当脚本访问该站点2500次时,它已经消耗了4GB或更多的RAM,并且停止工作。 是否可以在不关闭浏览器会话的情况下减少内存RAM的消耗? 我问这是因为,当我启动脚本时,需要手动登录该站点(两因素加成,下面未