Android踩内存,Android列表内存优化

android列表内存优化

背景

项目中有一个列表,准确的说是图片列表(整个列表都是图片)。可想而知占用的内存会很大。有什么优化的方法呢?

解决办法

对于这种场景,简单分析下。

首先图片肯定是通过图片加载框架执行加载的。

图片加载框架对于内存有一个最大的上限

磁盘缓存暂时不管,只分析内存

那么图片框架是如何和列表结合,实现图片的动态加载的呢?

就是说在不超过图片框架内存上限的前提下,最近使用的图片都会在内存中保存。这个一个限定值,总不能每次都在最大值边缘运行吧,还是要尽可能的优化。

以Picasso为例,Picasso默认会使用设备的15%的内存作为内存图片缓存。遇到上述的图片列表,内存一直占用在15%的上限肯定不行。

解决办法:列表item在不可见的状态下,尽可能的回收内存。

ImageView Bitmap有一个recycle()方法用于内存回收。重写ImageView的onDetachedFromWindow方法,在它从屏幕中消失时回调,去掉drawable引用,能加快内存的回收。

public class RecyclerImageView extends ImageView

{

...

@Override

protected void onDetachedFromWindow() {

super.onDetachedFromWindow();

setImageDrawable(null);

}

}

踩过的坑

通过上面的方法,好像减少了不少内存的使用(内存使用的最大值减小)。

但是,发现一个新的问题:在Item中存在NetCacheImageView(或者类似框架控件)时,偶尔会出现将一个条目刚刚滑动到看不见,然后将其拉回,其中的图片变为空白。

为什么会这样呢?

为了管理界面显示引用,框架扩展了ImageView中的setImageDrawable方法。在其中对旧的ImageDrawable引用计数减一,新的ImageDrawable计数加一。然后,为了在ImageView退出屏幕时及时回收Bitmap,扩展了onDetachedFromWindow方法,在其中调用setImageDrawable(null),以回收当前显示的Bitmap。至此之前我的关注点一直在图片加载的实现上,理清楚这个机制之后才考虑到是不是回收时机出了问题。

对RecyclerView进行分析之后我发现,当一个item被滑动到刚好看不见的位置时,触发了该item及其子View的onDetachedFromWindow,同样也就调用了setImageDrawable(null)。但是,RecyclerView.Adapter.onViewRecycled方法没有立刻被调用,而要等到继续滑动RecyclerView时才调用。也就是说,RecyclerView没有立即回收已经不在显示区域的item。如果此时将该item拉回,也不会再调用RecyclerView.Adapter.onBindViewHolder,也就是图片消失之后就不会再显示了。

分析:

说简单点就是:recyclerview源码就是最多加载两屏幕的view,就是说当前屏幕的一整屏幕view和列表上下两端的部分view。

但是,onDetachedFromWindow在Item view移出屏幕后就开始执行回收(drawable置为null,使bitmap更容易被回收)

这就是问题所在,当前屏幕上方的view图片引用被清空,可能被回收。如果滑动到此位子,recyclerview不会触发刷新。因此导致图片空白。

解决办法:

已经分析的很清楚了,相信答案也出来了。可以把setImageDrawable放在recyclerview的回收时释放,即onViewRecycled方法中。在adapter中重写此方法。

@Override

public void onViewRecycled(VideoViewHolder holder) {

if (holder != null && holder.getItemViewType() == VideoIndication.TYPE_VIDEO) {

holder.imgThumb.setImageDrawable(null);

}

super.onViewRecycled(holder);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值