安卓控件 listView 的学习及优化 (ConvetView、viewHolder)

(转载注明:http://blog.csdn.net/itermeng/article/details/52149426

一. listView 的学习

众所周知ListView 是一个控件,一个在垂直滚动的列表中显示条目的一个控件。


使用方法为:

1. 布局添加Listview 
2. 在对应的activity找到listview 
3. 创建一个Adapter适配器继承BaseAdapter,封装4个方法(如下图) 

getcount: 返回listview显示的条目总数。 
getItem : 返回当前点击listview的条目。 
getItemId : 返回点击条目对应在listview中的位置。 

getview:告诉listview每个条目显示的内容。

@Override
        public int getCount() {
            return 0;
        }
        @Override
        public Object getItem(int position) {
            return null;
        }
        @Override
        public long getItemId(int position) {
            return 0;
        }
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            return null;
        }

4. 创建Adapter的一个对象,设置给listview。 
listview.setAdapter(ListAdapter adapter);


二. listView 的优化

1.初步优化

依次封装以上4个方法,其中最重点的是 getview方法,主要的优化也是在其中。

    public View getView(int position, View convertView, ViewGroup parent) 
    {
            return null;
    }

注意观察getView方法中的参数,position为点击条目的具体位置,重点是 convertView ,一个listview中会有许多条目,而一个条目中可能由几个小控件(例如TextView、Button)组成,而 convertView指的是一个单独条目(View对象),它包括了那几个小控件。

为了让listview呈现出条目,在getView方法中我们需要不停的重新声明view对象,将layout布局inflate转换成view后,用findViewById获取一个条目中的具体控件进行赋值操作,如果需要大量条目展示,无疑这会消耗内存。

这里写图片描述

复用convertView : getview方法会传进来一个convertView,convertView是指曾经使用过的view对象,可以被重复使用,但是在使用前需要判断是否为空,不为空直接复用,并作为getview方法的返回对象。(如上图)

所以我们的第一步优化就是复用convertView(如下图所示)

扫描二维码关注公众号,回复: 3799022 查看本文章
public View getView(int position, View convertView, ViewGroup parent) {
    View view = null;
    if(convertView != null){//判断converView是否为空,不为空重新使用
        view = (TextView) convertView;
    }else{
        view = new TextView(mContext);//创建一个textView对象
        }
    return view;
}

再进行 if 判断之后,即复用完convertView对象后,再用findViewById获取小控件进行展示操作。

//2.获取view上的子控件对象
    TextView item_tv_title= (TextView) view.findViewById(R.id.item_tv_title);
    //3.获取postion位置条目对应的list集合中的新闻数据,Bean对象
    NewsBean newsBean = list.get(position);
    //4.将数据设置给这些子控件做显示
    item_tv_title.setText(newsBean.title);

这样看起来解决了问题,其实不然!如果现在需要展示100条 条目,虽然复用了对象,但是这意味着 findViewById的操作要重复100次,你的可用内存会慢慢减少,最后手机程序崩溃!(如下图)

这里写图片描述这里写图片描述




2.完全优化


优化重点:

1):复用convertView
(2):复用ViewHolder让其减少findViewById()次数
(3):static ViewHolder
(4):分页算法
  • 这里写图片描述

如上所说,不要去一味的 findViewByID(),它是一个耗时的操作,需要优化,使用viewHolder类,它把每一个条目View放在Holder中,当getView方法第一次创建convertView对象时,会把这些条目view找出来。然后用convertView的setTag将viewHolder设置到Tag中,这样下次呈现ListView时会直接从Tag中取出。当第二次复用convertView时,只需从convertView中getTag取出即可。(代码如下)

public View getView(int position, View convertView, ViewGroup parent) {
    //1,复用convertView   
            //复用viewHolder步骤一
            ViewHolder holder = null;
            if(convertView == null){
                convertView = View.inflate(getApplicationContext(), R.layout.listview_item, null);
                //2,减少findViewById()次数
                //复用viewHolder步骤三
                holder = new ViewHolder();
                //复用viewHolder步骤四
viewHolder.text1 = convertView.findViewById(R.id.text1);
                //复用viewHolder步骤五
                convertView.setTag(holder);
            }else{
                holder = (ViewHolder) convertView.getTag();
                 }
            viewHolder.text1.setText("文本内容");
}

//复用viewHolder步骤二
    static class ViewHolder{
        TextView text1;
    }

以上代码解析:

(1) convertView为空,代表当前条目是首次构建,就需要inflate转换布局,用findViewByID查找小控件,这是为了后面的条目去进行复用。 

(2)创建一个ViewHolder对象,去存储第一次找到的所有的小控件。当前的viewHolder对象,又由convertView去做存储。 setTag(viewHolder) 

(3)复用convertView的条目展示的时候,找到之前设置过的tag . ViewHolder viewHolder = getTag()viewHolder中就包含第一次构建时findViewById找过的小控件。


以上即为 listView控件的优化过程,至于分页涉及到 数据库分页查询,暂时不写。关于优化的讲解,其实直接讲第二点(完全优化)即可,但是我想循序渐进,因为初学者的我刚开始用listView使用得都是(初步优化),渐渐的才发现listView需要更彻底的优化,想让大家体会一点点深入的过程。希望对大家有所帮助 :)


猜你喜欢

转载自blog.csdn.net/JamieCheung/article/details/79385766