Android内存优化--自定义Adapter复用View

  ListView是一个非常常用的Android控件,通常情况下我们都需要去自定义ListView的Adapter以实现各种复杂的业务逻辑。但是需要注意的是,如果Adapter没有进行内存优化的话,ListView加载时会相当的占用内存,本文介绍了大部分情况下我们需要为自定义Adapter进行的内存优化工作。
  下边的代码都是我在MarkDown里边敲的,没有做代码检查,如果要直接复制的话最好检查一下有没有错误。


   内存优化的关键就是getView()方法,下边代码中省略了其他部分的逻辑。

应用情景:ListView中具有两种不同ListItem的布局,具有三种及以上也可参照此写法

  • 布局1含有TextView,ImageView两个控件
  • 布局2含有TextView,ImageView,Button三个控件

CustomAdapter.java

public class CustomAdapter extends BaseAdapter {
    //省略构造方法
    //省略其它复写方法
    @override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ListData itemData = getItem(position);
        ViewHolder1 holder1 = null;
        ViewHolder2 holder2 = null;
        //switch根据不同数据加载不同的布局
        switch(itemData.getDataType()){
            case ListData.TYPE_ONE:
                //下面这个R.id.item1这个id是我自己在values文件夹下的ids.xml添加的一个id,没有
                //任何实际意义,只是为了标识这个存储的Tag而已。由于官方推荐使用具有唯一性id作为Tag
                //的标识,所以需要自己去定义id,其中的原因有兴趣的可以去研究一下
                if (converView == null || converView.getTag(R.id.item1)){
                    //若是之前还没有过ViewHolder存储则本次新建ViewHolder并存储
                    converView == LayoutInflater.from(context)
                                    .inflate(R.layout.list_item1, parent, false);
                    holder1 = new ViewHolder1();
                    holder1.textView = (TextView)converView.findViewById(R.id.textview);
                    holder1.imageView = (ImageView)converView.findViewById(R.id.imageview);
                    converView.setTag(R.id.item1, holder1);
                } else {
                    //之前有过存储则直接使用
                    holder1 = (ViewHolder1)converView.getTag(R.id.item1);
                }
                holder1.textView.setText(ListData.getStr());
                holder1.imageView.setImageBitmap(BitmapFactory.decodeFile(ListData.getUrl));
                break;
            case ListData.TYPE_ONE:
                if (converView == null || converView.getTag(R.id.item2)){
                    //若是之前还没有过ViewHolder存储则本次新建ViewHolder并存储
                    converView == LayoutInflater.from(context)
                                    .inflate(R.layout.list_item2, parent, false);
                    holder2 = new ViewHolder2();
                    holder2.textView = (TextView)converView.findViewById(R.id.textview);
                    holder2.imageView = (ImageView)converView.findViewById(R.id.imageview);
                    holder2.button = (Button)converView.findViewById(R.id.button);
                    converView.setTag(R.id.item1, holder2);
                } else {
                    holder2 = (ViewHolder1)converView.getTag(R.id.item1);
                }
                holder2.textView.setText(ListData.getStr());
                holder2.imageView.setImageBitmap(BitmapFactory.decodeFile(ListData.getUrl));
                holder2.button.setText(ListData.getButtonName());
                break;
            default:
                break;

        }
        return convertView;
    }
    //布局1的ViewHolder
    class ViewHolder1{
        //定义布局包含的所有控件
        TextView textView;
        ImageView ImageView;
    }
    //布局2的ViewHolder
    class ViewHolder2{
        //定义布局内包含的所有控件
        TextView textView;
        ImageView ImageView;
        Button button;
    }
}

定义ListData数据格式方便Adapter使用数据
ListData.java

public class ListData{
    //存储数据的相关变量
    private int String str;
    private String url;
    private String buttonName;
    private int dataType;
    public static final int TYPE_ONE = 1;
    public static final int TYPE_TWO = 2;

    //数据格式1的构造函数
    public ListData(String str, String url){
        this.str = str;
        this.url = url;
        dataType = TYPE_ONE;
    }
    //数据格式2的构造函数
    public ListData(String str, String url, String buttonName){
        this.str = str;
        this.url = url;
        this.buttonName = buttonName;
        dataType = TYPE_TWO;
    }

    //相关get方法
    public String getStr(){
        return str;
    }

    public String getUrl(){
        return url;
    }

    public String getButtonName(){
        return ButtonName;
    }

    public int getDataType(){
        return dataType;
    }

}

定义两个id用来标识ViewHolder
values/ids.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item type="id" name="item1">item1</item>
    <item type="id" name="item2">item2</item>
</resources>

  大致思想就是这样子的,通过ViewHolder将初始化过的控件保存起来,下次可以不用新创建就能直接使用存储的控件。这样的话一个ListView如果有2种ListItem的形式,那么最多创建两个ViewHolder就可以搞定,大大节省了内存支出。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值