ViewPager里Bitmap主动回收资源的另一种思路

本文介绍了一种优化Android应用中轮播图内存占用的方法。通过改进PagerAdapter的实现,可以在不造成低端设备滑动卡顿的前提下,主动释放不再展示的Bitmap资源,有效减少内存消耗。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  Android是个资源吃紧的系统,虽然现在的手机运存越来越大,但是由于手机屏幕越来越大,加载的图片越来越大,加载后换算成内存占用也就越来越大,特别是用Bitmap直接不做任何压缩处理就加载显示的话,占用更大。因此我要分享其中的一种场景,我们可以主动去释放掉Bitmap资源,从而减轻内存占用。

场景:启动轮播图加载和释放优化

1.采用ViewPager + 多张图片来展示,加载数据的Adapter用继承于PagerAdapter的StaticPagerAdapter,类似参考FragmentStatePagerAdapter,是为了将所有要看的图片都加载到内存里面,这样用户左右滑动起来,就不会再触发初始化和销毁,这样就感觉很流畅,缺点就是占用内存大。
2.若采用类似FragmentPagerAdapter的话,就会默认销毁索引间距超过1的对象,这样内存不会占用过大,但是由于重复初始化,会造成低端手机滑动卡顿。
3.为了保持数据一致,所有图片加载显示时候都没有经过压缩处理。

传统的解决方法:

  在PagerAdapter里面复写 destroyItem 方法,然后主动回收图片:

public void releaseImageViewResouce(ImageView imageView) {  
    if (imageView == null) return;  
    Drawable drawable = imageView.getDrawable();  
    if (drawable != null && drawable instanceof BitmapDrawable) {  
        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;  
        Bitmap bitmap = bitmapDrawable.getBitmap();  
        if (bitmap != null && !bitmap.isRecycled()) {  
            bitmap.recycle();  
            bitmap=null;  
        }  
    }  
    System.gc();  
}

但是缺点也就是跟用FragmentPagerAdapter的一样,用户重新左滑回来的话,就又会出现重新初始化卡顿的情况。

新的解决方法:

  原则是我们需要保证滑动时候的顺畅,以及不需要的时候及时回收。所以在PagerAdapter相关继承类里面写一个方法,然后当不需要展示时候,从外部调用,进行整体的释放。

/**
  * 手动释放轮播引导图资源,不然内存会过非常久才可能会被gc回收
  * 从图像类里面获取,其中mViewList是静态Adapter里面存储的View集合。
  * */
 public void releaseAllImageRes() {
   for(View view : mViewList) {
       if(view instanceof ImageView) {
           ImageView imageView = (ImageView)view;
           imageView.setImageBitmap(null);
           BitmapUtil.releaseImageViewResouce(imageView);
         }
     }
 }
    /**
     * 释放图片资源
     * @param imageView
     */
    public static void releaseImageViewResouce(ImageView imageView) {
        if (imageView == null) return;
        Drawable drawable = imageView.getDrawable();
        if (drawable != null && drawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
            Bitmap bitmap = bitmapDrawable.getBitmap();
            if (bitmap != null && !bitmap.isRecycled()) {
                bitmap.recycle();
                bitmap=null;
            }
        }
        System.gc();
    }

  如此这样一来,我们可以主动触发recycle和gc,这样据我实测,1080P手机下的5张引导图,主动回收的话可以回收掉60M左右内存,如下图所示:

  但是有一点要注意,recycle这个不能随便用,你得确认后续app内不会再用这个资源时候才能主动这么调用,否则有可能出现你要再次使用的时候,报错。如源码里面的解释:

/**
 * Free the native object associated with this bitmap, and clear the
 * reference to the pixel data. This will not free the pixel data synchronously;
 * it simply allows it to be garbage collected if there are no other references.
 * The bitmap is marked as "dead", meaning it will throw an exception if
 * getPixels() or setPixels() is called, and will draw nothing. This operation
 * cannot be reversed, so it should only be called if you are sure there are no
 * further uses for the bitmap. This is an advanced call, and normally need
 * not be called, since the normal GC process will free up this memory when
 * there are no more references to this bitmap.
 */

参考文章:http://blog.youkuaiyun.com/bobxie520/article/details/51167957

原创文章,欢迎转载,转载请注明:ifish.site
作者:JaydenZhou

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JaydenZhou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值