Android学习心得第五课

来源:互联网 发布:女孩子淘宝收件人名字 编辑:程序博客网 时间:2024/05/22 06:55

今天算是遇到了Android学习上面的一块硬骨头了,目前算是基本理解了,后面还是要时不时的来回顾一下,温故而知新,下面就来回顾一下我今天学习的知识, 今天的知识点就一个那就是关于BaseAdapter,
上一节心得,我专门对数据适配器进行了一个解释,今天在慕课上看到一个比较好的图,这里分享一下。
这里写图片描述
从图中我们可以看出为什么需要数据适配器这么一个东西,因为数据源是各种各样的,但是listview它所接受的格式却是固定的,这个时候我们就需要数据适配器这么一个中间件,通过数据适配器来将数据源转换成llistview所能够接受的那种数据。

那么BaseAdapter究竟希望它能够干什么能,它主要是比较灵活,可以进行各种的改写,listview有一个缓存机制,如下图:
这里写图片描述
通过这种机制我们可以大大的减轻内存的开销。
下面我就来具体解释一下关于BaseAdapter的事情。首先在这里有一个小技巧,就是利用bean对象,将需要的数据先封装起来。

public class MyBaseAdapter extends BaseAdapter {    // 映射数据    List<ItemBean> datalist;    private long mSumTime;    /*     * LayoutInflater这个类它的作用类似于findViewById()。     * 不同点是LayoutInflater是用来找res/layout/下的xml布局文件,并且实例化;     * 而findViewById()是找xml布局文件下的具体widget控件(如Button、TextView等)。     */    private LayoutInflater mLayoutInflater;    public MyBaseAdapter(Context context, List<ItemBean> datalist) {        this.datalist = datalist;        mLayoutInflater = LayoutInflater.from(context);    }    // 获取数据量    @Override    public int getCount() {        // TODO Auto-generated method stub        return datalist.size();    }    // 获取对应ID的对应Item    @Override    public Object getItem(int position) {        // TODO Auto-generated method stub        return datalist.get(position);    }    // 获取对应的ID    @Override    public long getItemId(int position) {        // TODO Auto-generated method stub        return position;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {         TODO Auto-generated method stub         //第一种方式(不加任何的优化)----------------------------------------------         //该函数的作用是为了将xml文件转换成View,这里因为不涉及第二个参数,所以第二个参数为空         View view = mLayoutInflater.inflate(R.layout.item, null);         // 实例化控件         ImageView itemImage = (ImageView) view.findViewById(R.id.iv_image);         TextView itemTitle = (TextView) view.findViewById(R.id.tv_title);         TextView itemContent = (TextView) view.findViewById(R.id.tv_content);         // 去除bean对象         ItemBean bean = datalist.get(position);         // 设置控件的数据         itemImage.setImageResource(bean.itemImageResId);         itemTitle.setText(bean.itemTitle);         itemContent.setText(bean.itemContent);         return view;

第一种方法的一个巨大的缺点就在于,它每次调用getView函数的时候,都要新建一个View对象,这样的话十分占用资源,而且也没有用到ListView的缓存机制,这里我们对其进行一个改进,下面放入getView的代码。
(2)第二种方式 利用 ListView 的缓存机制进行改进

/*  * 第二种方式(加入优化)--第一种方法的弊端是每次调用getview的时候都要新建一个View对象  * 这种方法十分占用内存,因为每次都需要新建一个View对象,这里运用到了listview的缓存机制,也就是  * 该函数的第二个参数convertView,通过使用它可以大大的减少内存的开销 当listview对象非常复杂的时候这种方法十分有效。 */         if (convertView == null) {         // 这种逻辑的意思就是当convertView为空时,说明是第一次调用,缓存为空,所以将该布局        // 转换为View放入convertView中,当再次调用时不用再像第一种方法一样每次都新建一个view            convertView = mLayoutInflater.inflate(R.layout.item, null);         }              ImageView itemImage = (ImageView) convertView                                    .findViewById(R.id.iv_image);              TextView itemTitle = (TextView)convertView                                    .findViewById(R.id.tv_title);               TextView itemContent = (TextView) convertView                                    .findViewById(R.id.tv_content);               ItemBean bean = datalist.get(position);               itemImage.setImageResource(bean.itemImageResId);               itemTitle.setText(bean.itemTitle);               itemContent.setText(bean.itemContent);               return convertView;

这里和上式相比,利用convertView参数来避免了每次重复新建View对象,但是这种对象还没达到最佳的优化,因为findViewById这个函数每次在执行的时候是需要遍历整个视图树,当视图树比较复杂的时候,这个遍历的时间将会相当的可观。所以这里可以用到Google提出的一个新的方法—-ViewHolder。下面我们来看看代码。

        /*         * 第三种方法(最佳版本)这种版本在第二种版本的基础上进一步的优化了findViewById这一个过程         * 因为其实每做一次findViewById的时候,都要遍历整个视图树,如果视图树比较复杂的话         * 遍历的时间将会想当的客观,所以Google专门给了一种数据结构叫ViewHolder         * 同样是运用了缓存的机制,将已经遍历过的主键的ID给存起来         */         // 获取纳秒时间 更加精确        ViewHolder holder = null;        if (convertView == null) {            holder = new ViewHolder();            convertView = mLayoutInflater.inflate(R.layout.item, null);            holder.image = (ImageView) convertView.findViewById(R.id.iv_image);            holder.title = (TextView) convertView.findViewById(R.id.tv_title);            holder.content = (TextView) convertView                    .findViewById(R.id.tv_content);            //将Viewholder与convertView通过setTag绑定起来            convertView.setTag(holder);        }        else {            //getTag()取出关联的ViewHolder            //通过ViewHolder对象找到对应的控件            holder = (ViewHolder) convertView.getTag();        }        ItemBean bean = datalist.get(position);        holder.image.setImageResource(bean.itemImageResId);        holder.title.setText(bean.itemTitle);        holder.content.setText(bean.itemContent);        return convertView;    }    class ViewHolder {        public ImageView image;        public TextView title;        public TextView content;    }}

最后一种方法不仅利用了ListView的缓存机制,更是通过ViewHolder来实现数据视图的缓存,避免了多次通过findViewById来寻找控件,在今后的程序思路中也应该借用这种思想。
最后对利用ViewHolder来优化BaseAdapter的思路做一下总结。
(1)创建Bean对象,用于封装数据
(2)在构造方法中初始化用于映射的数据list
(3)创建ViewHolder类,创建布局映射关系
(4)判断convertView,为空则创建,并设置tag,如果不为空则通过tag取出对应的ViewHolder
(5)给ViewHolder中的控件设置数据

0 0
原创粉丝点击