封装一个工具类:回收任何布局中被Imageview吃掉的内存(附源码DEMO)

在android程序中,为了避免OOM的出现,最为直接的方式就是将Bitmap占用的内存Recycle掉。但是在一个布局或者控件中,图片非常多,来源又不一样。这个时候,写代码手动的释放,也蛮费事的。

  所以我封装了一个工具类,只要将当前activity所在的布局传入工具类,工具类会自动释放布局中所有Imageview占用的图片资源。

   说明:此工具类用于回收布局中被Imageview占用的图片资源,传入根布局,或者继承自ViewGroup类的子类。

适用范围:  ViewGroup的直接或间接子类

   常用的的布局类(如线性布局,相对布局,帧布局,绝对布局)都是继承自ViewGroup基类,为了弄明白适用范围,我们来看一下ViewGroup的直接和间接子类: 

Known Direct Subclasses(儿子辈)

AbsoluteLayout, AdapterView<T extends Adapter>, FragmentBreadCrumbs, FrameLayout, GridLayout, LinearLayout,

 PagerTitleStrip, RelativeLayout,SlidingDrawer, ViewPager

ImageKnown Indirect Subclasses(孙子辈)

AbsListView
Base class that can be used to implement virtualized lists of items.

AbsSpinner
An abstract base class for spinner widgets.

AdapterViewAnimator
Base class for a AdapterView that will perform animations when switching between its views.

AdapterViewFlipper
Simple ViewAnimator that will animate between two or more views that have been added to it.

AppWidgetHostView
Provides the glue to show AppWidget views.

CalendarView
This class is a calendar widget for displaying and selecting dates.

DatePicker
This class is a widget for selecting a date.

DialerFilter

ExpandableListView
A view that shows items in a vertically scrolling two-level list.

Gallery
This class was deprecated in API level 16. This widget is no longer supported. Other horizontally scrolling widgets includeHorizontalScrollView and ViewPager from the support library.

GestureOverlayView
A transparent overlay for gesture input that can be placed on top of other widgets or contain other widgets.

GridView
A view that shows items in two-dimensional scrolling grid.

HorizontalScrollView
Layout container for a view hierarchy that can be scrolled by the user, allowing it to be larger than the physical display.

ImageSwitcher

ListView
A view that shows items in a vertically scrolling list.

MediaController
A view containing controls for a MediaPlayer.

NumberPicker
A widget that enables the user to select a number form a predefined range.

PagerTabStrip
PagerTabStrip is an interactive indicator of the current, next, and previous pages of a ViewPager.

RadioGroup

This class is used to create a multiple-exclusion scope for a set of radio buttons.

ScrollView
Layout container for a view hierarchy that can be scrolled by the user, allowing it to be larger than the physical display.

SearchView
A widget that provides a user interface for the user to enter a search query and submit a request to a search provider.

Spinner
A view that displays one child at a time and lets the user pick among them.

StackView

TabHost
Container for a tabbed window view.

TabWidget
Displays a list of tab labels representing each page in the parent’s tab collection.

TableLayout

A layout that arranges its children into rows and columns.

TableRow

A layout that arranges its children horizontally.

TextSwitcher
Specialized ViewSwitcher that contains only children of type TextView.

TimePicker
A view for selecting the time of day, in either 24 hour or AM/PM mode.

TwoLineListItem

A view group with two children, intended for use in ListViews.

ViewAnimator
Base class for a FrameLayout container that will perform animations when switching between its views.

ViewFlipper
Simple ViewAnimator that will animate between two or more views that have been added to it.

ViewSwitcher
ViewAnimator that switches between two views, and has a factory from which these views are created.

WebView

A View that displays web pages.

ZoomControls
The ZoomControls class displays a simple set of controls used for zooming and provides callbacks to register for events.

  以上内容在ViewGroup的文档中都有介绍,这里不再赘述。

  回收的内容:

  说完了布局文件,接下来说一下需要回收Imageview中的哪些东东。

  ImageView显示图片有两种方式:

  1.代码或者xml文件中设置为背景

  2.代码或者xml文件中设置Imageview的内容,如xml中的src,代码中的setImageResource等等。

  总之,看起来背景图片和内容图片不一样,我们分开回收。默认回收内容图片,背景图片是否回收可以自行设置。

  使用场景:

  当Activity退出时,需要清理和释放图片资源时,使用此类。

  好了,废话不多说了,上代码:

package com.liubing;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
 
/**
 * 工具类
 * 释放布局中所有Imageview组件占用的图片,可设置是否释放背景图
 * 用于退出时释放资源,调用完成后,请不要刷新界面
 * @author liubing
 *
 */
public class RecycleBitmapInLayout {
    private static final String TAG = "RecycleBitmapInLayout";
    /*是否释放背景图  true:释放;false:不释放*/
    private boolean flagWithBackgroud = false;  
    
    /**
     * 
     * @param flagWithBackgroud 是否同时释放背景图
     */
    public RecycleBitmapInLayout(boolean flagWithBackgroud) {
        this.flagWithBackgroud = flagWithBackgroud;
    }
 
    /**
     * 释放Imageview占用的图片资源
     * 用于退出时释放资源,调用完成后,请不要刷新界面
     * @param layout 需要释放图片的布局     * 
     */
    public void recycle(ViewGroup layout) {
        
        
        for (int i = 0; i < layout.getChildCount(); i++) {
            //获得该布局的所有子布局
            View subView = layout.getChildAt(i);
            //判断子布局属性,如果还是ViewGroup类型,递归回收
            if (subView instanceof ViewGroup) {
                //递归回收
                recycle((ViewGroup)subView);
            } else {
                //是Imageview的子例
                if (subView instanceof ImageView) {
                    //回收占用的Bitmap
                recycleImageViewBitMap((ImageView)subView);
                    //如果flagWithBackgroud为true,则同时回收背景图
                if (flagWithBackgroud) {
                    
                    recycleBackgroundBitMap((ImageView)subView);
                }
                }
            }
        }
    }
    
    private void recycleBackgroundBitMap(ImageView view) {
        if (view != null) {
            BitmapDrawable bd = (BitmapDrawable) view.getBackground();
            rceycleBitmapDrawable(bd);
        }
    }
 
    private void recycleImageViewBitMap(ImageView imageView) {
        if (imageView != null) {
            BitmapDrawable bd = (BitmapDrawable) imageView.getDrawable();
            rceycleBitmapDrawable(bd);
        }
    }
 
    private void rceycleBitmapDrawable(BitmapDrawable bd) {
        if (bd != null) {
            Bitmap bitmap = bd.getBitmap();
            rceycleBitmap(bitmap);
        }
        bd = null;
    }
 
    private void rceycleBitmap(Bitmap bitmap) {
        if (bitmap != null && !bitmap.isRecycled()) {
            Log.e(TAG, "rceycleBitmap");
            bitmap.recycle();
            bitmap = null;
        }
    }
 
}

 

使用方法:当退出activity时调用,如

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    // TODO Auto-generated method stub
    if (keyCode == event.KEYCODE_BACK && event.getRepeatCount() == 0) {
        //回收图片
        new RecycleBitmapInLayout(true).recycle(rootLayout);
        //退出时,请求杀死进程
        android.os.Process.killProcess(android.os.Process.myPid());
    }
    return super.onKeyDown(keyCode, event);
}

存在问题:释放的时机不恰当,会造成”trying to use a recycled bitmap android.graphics.Bitmap”的错误,请谨慎使用

总结:是一个管杀不管埋的工具类。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值