ViewHolder

来源:互联网 发布:mac大型单机游戏下载 编辑:程序博客网 时间:2024/06/05 00:09

做过安卓开发,基本都知道ListView,GridView等控件是使用适配器来绑定数据到视图上的,而他们都使用了视图回收来优化列表滚动,避免的频繁地创建和销毁条目(Item)视图(哈哈,这有点像异步消息处理机制中Message对象的回收哈)。

那么系统已经优化了又有我们什么事呢?原因在于当item一多,滑动时,特别是快速滑动,不断地调用适配器getView()方法,那么我们在getView里面所做的事情就严重影响到滑动的流畅程度了,比如执行一次需要一秒,那么滑动复用一条item时就会卡那里一秒,一千条。。。。。。

那么问题来了,我们在getView里面做了什么事情呢?没错不就是创建视图(或使用已回收的视图)寻找里面的子控件并绑定数据吗?如同从LinearLayout中找到一个TextView并调用setText()设置显示文本。

这个过程中,有哪些是可以优化的呢?由于每个item的显示文本可能都不一样,所以setText()这个过程是必不可少的,那么寻找子控件的过程呢?ListView每个item都有一样的一组控件,而我们每次都要从里面找到一个特定的控件来设置显示数据,这个过程我们一般都是用findViewById来实现,遍历一整组的控件(控件通常含有子控件,层层遍历)直到找到了那个特定ID的控件为止,明显这个过程是比较耗时的,而我们每次执行getView都在做着同样的遍历查找工作。

所以有了ViewHolder,查找完一次将结果(控件引用缓存起来),下次直接用,不需要再查找。
由于每个ViewHolder保存的控件引用都是对应当前条目视图的,所以将ViewHolder对象保存在视图对象中,如果视图是回收来的,他身上就有ViewHolder对象,我们直接取出就可以轻易拿到我们要的控件了

@Override        public View getView(int position, View convertView, ViewGroup parent) {            Item currentItem = items.get(position);            ViewHolder viewHolder;            if (convertView == null) {                convertView = LayoutInflater.from(context).inflate(R.layout.item_lv_headword, parent, false);                viewHolder = new ViewHolder(convertView);                convertView.setTag(viewHolder);            } else {                viewHolder = (ViewHolder) convertView.getTag();            }            viewHolder.tv_headword_item_name.setText(currentItem.name);            return convertView;        }
static class ViewHolder {        private TextView tv_headword_item_name;        public ViewHolder(View convertView) {            //因为每次创建视图只需执行一次findViewById,所以放在构造方法中            tv_headword_item_name = (TextView) convertView.findViewById(R.id.tv_headword_item_name);        }    }    static class ItemData {        private String name;        private ItemData(String name) {            this.name = name;        }    }

这样我们就实现使用ViewHolder优化ListView的滑动(其实就是优化调用findViewById()的次数)
其实这个大家都懂,我只是想锻炼一下表述能力,但貌似还是没表达好

关于ViewHolder为何要使用静态内部类的问题:
网上有人说静态是让他无论new多少次ViewHolder都只存在一个实例,不会重新分配内存,以此达到节省内存的目的,,,

我只想说,,,略坑,面试被问到这么答除了暴露java基础不好,智商不够,没别的了

推荐使用静态内部类是因为静态内部类比普通的内部类性能高。那他们肯定有区别,不然怎么会静态的性能比较高呢?
没错的,还记得写代码时想在普通的内部类里面调用外部类方法吗?没错,直接调就行了(或者外部类类名.this.方法名)why?因为内部类默认持有了外部类的引用,(可以看成是内部类里面有个成员变量,这个成员变量是外部类的实例,当然事实不是这样的),那么这个引用就得有人为他赋值,这个赋值过程不知道是怎样的,但明显会多执行些代码,不然也不会建议使用静态内部类了

0 0
原创粉丝点击