ListView优化之BaseAdapter使用小心得



(初学者)

当我们需要通过滚动屏幕来显示我们需要的item时候,如果一次次findViewById的话效率极低。这里BaseAdapter这个库可以解决这个问题。

通过改写库里面getView()方法,可以实现旧item的缓存,以及再一次使用时候的调出。

BaseAdaper类的介绍:BaseAdapter就是Android应用程序中经常用到的基础数据适配器,它实现了ListAdapter和SpinnerAdapter两个接口。且其主要用途是将一组数据传到像ListView、Spinner、Gallery及GridView等UI显示组件。

Android中Adapter类其实就是把数据源绑定到指定的View上,然后再返回该View,而返回来的这个View就是ListView中的某一行item。这里返回来的View正是由于我们的Adapter中的getView方法返回的。也就是说当我们想做一个列表形式的界面时,我们通常会用到Adapter类,而BaseAdapter则是其中一个很灵活的类。我们可以通过改写BaseAdapter类中的方法来灵活的将数据传到UI显示组件进行显示。

getView()介绍:这个方法是BaseAdapter类中最重要的一个部分,合理的改写此部分可以很好地提高代码效率。这里大概有3种getView()的写法。

第一种:没有任何处理,不建议这样写。如果数据量少看将就,但是如果列表项数据量很大的时候,会每次都重新创建View,设置资源,严重影响性能,所以从一开始就不要用这种方式

1.@Override
2.        public View getView(int position, View convertView, ViewGroup parent) {
3.            View item = mInflater.inflate(R.layout.list_item, null);
4.            ImageView img = (ImageView)item.findViewById(R.id.img)
5.            TextView title = (TextView)item.findViewById(R.id.title);
6.            TextView info = (TextView)item.findViewById(R.id.info);
7.            img.setImageResource(R.drawable.ic_launcher);
8.            title.setText("Hello");
9.            info.setText("world");
10.                                                                                                                        
11.            return item;
12.        }

第二种:通过缓存convertView,这种利用缓存contentView的方式可以判断如果缓存中不存在View才创建View,如果已经存在可以利用缓存中的View,提升了性能

1.public View getView(int position, View convertView, ViewGroup parent) {
2.            if(convertView == null)
3.            {
4.                convertView = mInflater.inflate(R.layout.list_item, null);
5.            }
6.                                                                                            
7.            ImageView img = (ImageView)convertView.findViewById(R.id.img)
8.            TextView title = (TextView)convertView.findViewById(R.id.title);
9.            TextView info = (TextView)ConvertView.findViewById(R.id.info);
10.            img.setImageResource(R.drawable.ic_launcher);
11.            title.setText("Hello");
12.            info.setText("world");
13.                                                                                            
14.            return convertView;
15.        }
第三种:通过convertView+ViewHolder来实现,ViewHolder就是一个静态类,使用 ViewHolder 的关键好处是缓存了显示数据的视图(View),加快了 UI 的响应速度。

当我们判断 convertView == null  的时候,如果为空,就会根据设计好的List的Item布局(XML),来为convertView赋值,并生成一个viewHolder来绑定converView里面的各个View控件(XML布局里面的那些控件)。再用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。(看下面代码中)

如果convertView不为空的时候,就会直接用convertView的getTag(),来获得一个ViewHolder。 

1.//在外面先定义,ViewHolder静态类
2.static class ViewHolder
3.{
4.    public ImageView img;
5.    public TextView title;
6.    public TextView info;
7.}
8.//然后重写getView
9.@Override
10.public View getView(int position, View convertView, ViewGroup parent) {
11.    ViewHolder holder;
12.    if(convertView == null)
13.    {
14.        holder = new ViewHolder();
15.        convertView = mInflater.inflate(R.layout.list_item, null);
16.        holder.img = (ImageView)item.findViewById(R.id.img)
17.        holder.title = (TextView)item.findViewById(R.id.title);
18.        holder.info = (TextView)item.findViewById(R.id.info);
19.        convertView.setTag(holder);
20.    }else
21.    {
22.        holder = (ViewHolder)convertView.getTag();
23.    }
24.        holder.img.setImageResource(R.drawable.ic_launcher);
25.        holder.title.setText("Hello");
26.        holder.info.setText("World");
27.    }
28.                                                                                                
29.    return convertView;
30.}

 其中第二种和第三种最大的区别就在于,ViewHolder模式通过getView()方法返回的视图的标签(Tag)中存储一个数据结构,这个数据结构包含了指向我们

要绑定数据的视图的引用,从而避免每次调用getView()的时候调用findViewById()


这里再简单介绍一下getView中比较重要的类:

ViewHolder

ViewHolder通常出现在适配器里,为的是listview滚动的时候快速设置值,而不必每次都重新创建很多对象,从而提升性能。在android开发中Listview是一个很重要的组件,它以列表的形式根据数据的长自适应展示具体内容,用户可以自由的定义listview每一列的布局,但当listview有大量的数据需要加载的时候,会占据大量内存,影响性能,这时候就需要按需填充并重新使用view来减少对象的创建。

可以看到代码部分定义一个viewholder类,屏幕每次显示一个item时候会调用一次getView()方法,通过setTag()将我们所显示的item保存起来缓存在我们的ViewHolder类中,从而在我们下一次显示旧item时候直接从ViewHolder中通过getTag()调出。



        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
             ViewHolder holder;
            if (convertView == null) {
                     convertView = mInflater.inflate(R.layout.item,
    null);
                     holder = new ViewHolder();
                    /*得到各个控件的对象*/
                    holder.title = (TextView) convertView.findViewById(R.id.ItemTitle);
                    holder.text = (TextView) convertView.findViewById(R.id.ItemText);
                    holder.bt = (Button) convertView.findViewById(R.id.ItemButton);
                    convertView.setTag(holder);//绑定ViewHolder对象
                   }
    else{
                    holder = (ViewHolder)convertView.getTag();//取出ViewHolder对象
                  }
            /*设置TextView显示的内容,即我们存放在动态数组中的数据*/
            holder.title.setText(getDate().get(position).get("ItemTitle").toString());
            holder.text.setText(getDate().get(position).get("ItemText").toString());
            return convertView;
        }



你可能感兴趣的:(ListView优化之BaseAdapter使用小心得)