listView系列之优化问题

今天,稍微记录下前几天系统学习的listView的一个优化问题,在这里我们会对几种listView的解决方式来进行比较,从而看出优化后的优点。
首先我们来进行一下前期的准备工作。

public class MainActivity extends Activity {

    private ListView mListview;

    private List<String> datas;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        datas=new ArrayList<String>();
        for (int i = 1; i <= 100; i++) {
           datas.add(i+"");
        }

        mListview = (ListView) findViewById(R.id.listView);

        mListview.setAdapter(new Myadapter());
        }
    }

这是MainActivity 中的简单的listView的使用,就不注释了(这里的布局文件就是一个简单ListView)。

一:接着,我们为了侧重讲优化,就直接简单点,将适配器adpater的代码作为内部类放在MainActivity 内部就行,下面就是放在MainActivity 内部的代码:

public class Myadapter extends BaseAdapter {

        @Override
        public int getCount() {
            return datas.size();
        }

        @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) {

            // 逗逼式:如果单单这样写完全没有对listVie的任何优化处理,没起到一个复用
             View view = View.inflate(MainActivity.this, R.layout.my_item, null);
             TextView tv (TextView)view.findViewById(R.id.item_tv);
             tv.setText(datas.get(position));
    return view;
            }
    }       

在这里就是我们常见的一般的写listView的方式(这里的布局文件my_item就是一个简单的TextView),这种方式就像我注释上写的是一样的,是一种逗逼式的方法,因为完全没有起到listview中getView这个方法中的convertView这个参数来起到一个复用的作用。
这里的View.inflate这行代码的刚开始调用的次数是屏幕上第一次显示的数目,比如运行时屏幕上只显示了4个,也就是调用了四次,但当我们向下滑动,出现余下item时会同样调用,并且当我们向上滑动时也同样会重复的调用view.inflate这行代码,这样的缺点会导致当我们不停滑动listview时会发现会越来越卡顿


二:接下来就是采用convertView来进行一般的优化,其实简单点说就是解决上面的view.inflate这行代码重复调用的缺点,在这里,我们主要进行优化的代码放在getView的方法中:

/*
             * 当listView的第一条条目Item完全出去在屏幕外时,会放在一个叫recycle的回收站中,
             * 所以convertView就是起到一个复用的作用,其实就是上面在recycle回收站中第一条条目的视图,
             * 等着后面去复用视图,后面只是更换数据而已 conVertView为null时就是第一次显示在屏幕上的item条数
             * 
             */
            /// 普通式:虽然这里起到一个复用的作用,但是在这里的textView的findViewByID还是没起到复用
             if (convertView == null) {
             convertView = View.inflate(MainActivity.this, R.layout.my_item,null);
             }
             TextView tv = (TextView) convertView.findViewById(R.id.item_tv);
             tv.setText(datas.get(position));
             return convertView

在这里,当convertView为空时才会进行view.inflate这行代码,如果不为空,则直接用之前的convertView.findViewById..即可。而当convertView为空的个数是就是第一次显示在屏幕上的item数目,也就是下图中的四个item数。
在接下来的图中就表现出优点:
这里写图片描述
但是虽然已经比之前的做了优化,但是就像我注释中写的一样,这种方法没有实现TextView的findViewById的复用。


三:所以针对第二种的findViewById没有复用的缺点继续进行优化,我们在这里采用ViewHodler来进行最后的优化:首先我们来写一个内部类的Viewholder:

static class ViewHodle {
        TextView textview;
    }

在这里注意不管是内部类还是外部类,尽量使用static来修饰,这样做的目的是让其加载一次,并且减少内存占用,加快效率。

接着是getView的方法:

/// 优化式:在这里不仅引用上面的convertView的复用,同样利用Viewhodle来使用其中控件的findViewByID复用
            ViewHodle hodler;
            ///这里的convertView instanceof ViewGroup是对convertView来进行
            if (convertView ==null) {
            convertView = View.inflate(MainActivity.this, R.layout.my_item, null);
                hodler = new ViewHodle();
                hodler.textview = (TextView) convertView.findViewById(R.id.item_tv);
                convertView.setTag(hodler);
            } else {
                hodler = (ViewHodle) convertView.getTag();
            }
            holder.textview.setText(datas.get(position));
            return convertView;

这里就是好的优化方式,不仅使用了convertView的复用,并且解决了findViewById的重复调用,其实简单的来说这里就是用了Viewholder来实现一个简单的缓存而已。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值