viewholder
现在,我们将对Android ListView的平滑滚动进行编码。 在上一篇文章中 ,我们试图了解带适配器的ListView的工作方式。 这次,一切将与性能有关。
我之所以单独发表这篇文章是因为有时很难理解Android ListView 。 我想到的是:“我们必须先做基础,然后再应用优化。”
ViewHolder模式是什么?
ViewHolder设计模式使您无需查找即可访问每个列表项视图,从而节省了宝贵的处理器周期。 具体来说,它避免了ListView滚动期间频繁调用findViewById()并使它变得平滑。
没有ViewHolder设计模式
好的,让我们深入研究一下,看看它在没有 ViewHolder模式的情况下如何工作。
让我们看看ArrayAdapterItem.java中以前的 getView()方法
- 第一次加载时,convertView为null。 我们将不得不增加列表项的布局,并通过findViewById()找到TextView。
- 第二次加载时,convertView不为null,很好! 我们不必再给它充气。 但是,我们将再次使用findViewById()。
- 在以下几次加载时,convertView绝对不为null。 但是findViewById()会不断地被调用,它将起作用,但是,它会降低性能,特别是如果ListView中有很多项目和视图时。
使用ViewHolder设计模式
现在,让我们看看它如何与 ViewHolder模式一起使用。
- 第一次加载时,convertView为null。 我们将不得不增加列表项的布局,实例化ViewHolder,通过findViewById()找到TextView并将其分配给ViewHolder,然后将ViewHolder设置为convertView的标记。
- 第二次加载时,convertView不为null,很好! 我们不必再给它充气。 令人高兴的是,由于我们现在可以通过其ViewHolder访问TextView,因此不必调用findViewById()。
- 下次加载时,convertView绝对不为null。 不再调用findViewById(),这使我们的ListView平滑滚动。
让我们编码!
就是这样,我们将在ListView中使用Android ViewHolder模式 (仅3个步骤!)。
步骤1 :在我们的ArrayAdapterItem.java文件中添加以下静态类
// our ViewHolder.
// caches our TextView
static class ViewHolderItem {
TextView textViewItem;
}
步骤2 :我们的getView()现在看起来像这样:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolderItem viewHolder;
/*
* The convertView argument is essentially a "ScrapView" as described is Lucas post
* http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/
* It will have a non-null value when ListView is asking you recycle the row layout.
* So, when convertView is not null, you should simply update its contents instead of inflating a new row layout.
*/
if(convertView==null){
// inflate the layout
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
convertView = inflater.inflate(layoutResourceId, parent, false);
// well set up the ViewHolder
viewHolder = new ViewHolderItem();
viewHolder.textViewItem = (TextView) convertView.findViewById(R.id.textViewItem);
// store the holder with the view.
convertView.setTag(viewHolder);
}else{
// we've just avoided calling findViewById() on resource everytime
// just use the viewHolder
viewHolder = (ViewHolderItem) convertView.getTag();
}
// object item based on the position
ObjectItem objectItem = data[position];
// assign values if the object is not null
if(objectItem != null) {
// get the TextView from the ViewHolder and then set the text (item name) and tag (item ID) values
viewHolder.textViewItem.setText(objectItem.itemName);
viewHolder.textViewItem.setTag(objectItem.itemId);
}
return convertView;
}
第3步 :为了进行测试,我们将在ListView中放入数千个项目。 在MainActivity.java上,我们的showPopUp()现在看起来像这样:
public void showPopUp(){
// we'll specify the number of items we want our ListView to have.
int numberOfItems = 1000;
// add your items, this can be done programatically
// your items can be from a database
ObjectItem[] ObjectItemData = new ObjectItem[numberOfItems];
// we'll use a for loop
// created objects = number of items specified above
for(int x=0; x<numberOfItems; x++){
int sampleId = 90 + x;
ObjectItemData[x] = new ObjectItem(sampleId, "Store # " + (x+1));
}
// our adapter instance
ArrayAdapterItem adapter = new ArrayAdapterItem(this, R.layout.list_view_row_item, ObjectItemData);
// create a new ListView, set the adapter and item click listener
ListView listViewItems = new ListView(this);
listViewItems.setAdapter(adapter);
listViewItems.setOnItemClickListener(new OnItemClickListenerListViewItem());
// put the ListView in the pop up
alertDialogStores = new AlertDialog.Builder(MainActivity.this)
.setView(listViewItems)
.setTitle("Stores")
.show();
}
我用多达2,000个项目测试了此代码,并且性能仍然非常出色。
下一步是什么?
如果您对此主题还有其他想法,请将其放在下面的评论部分。 我非常乐意更新这篇文章并改善人类生活。
在下一篇文章中,我们将尝试使用AsyncTask将图像加载到ListView中。 诸如Google Play商店应用的操作方式。
翻译自: https://www.javacodegeeks.com/2013/09/android-viewholder-pattern-example.html
viewholder