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

时间:2021-11-10 01:28:25

(转载注明: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获取一个条目中的具体控件进行赋值操作,如果需要大量条目展示,无疑这会消耗内存。

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

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

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

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次,你的可用内存会慢慢减少,最后手机程序崩溃!(如下图)

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




2.完全优化


优化重点:

1):复用convertView
2):复用ViewHolder让其减少findViewById()次数
3):static ViewHolder
4):分页算法

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

如上所说,不要去一味的 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需要更彻底的优化,想让大家体会一点点深入的过程。希望对大家有所帮助 :)