viewholder_Android ViewHolder模式示例

本文详细介绍了Android中的ViewHolder设计模式,旨在提高ListView滚动时的性能。通过对比没有使用ViewHolder时频繁调用findViewById()导致的性能问题,阐述了ViewHolder模式如何避免这个问题,确保ListView平滑滚动。文中还提供了实现ViewHolder模式的3个步骤,以及测试大量项目时依然表现出的优秀性能。
摘要由CSDN通过智能技术生成

viewholder

现在,我们将对Android ListView的平滑滚动进行编码。 在上一篇文章中 ,我们试图了解带适配器的ListView的工作方式。 这次,一切将与性能有关。

我之所以单独发表这篇文章是因为有时很难理解Android ListView 。 我想到的是:“我们必须先做基础,然后再应用优化。”

ViewHolder模式是什么?

ViewHolder设计模式使您无需查找即可访问每个列表项视图,从而节省了宝贵的处理器周期。 具体来说,它避免了ListView滚动期间频繁调用findViewById()并使它变得平滑。

没有ViewHolder设计模式

好的,让我们深入研究一下,看看它在没有 ViewHolder模式的情况下如何工作。

让我们看看ArrayAdapterItem.java中以前的 getView()方法

  1. 第一次加载时,convertView为null。 我们将不得不增加列表项的布局,并通过findViewById()找到TextView。
  2. 第二次加载时,convertView不为null,很好! 我们不必再给它充气。 但是,我们将再次使用findViewById()。
  3. 在以下几次加载时,convertView绝对不为null。 但是findViewById()会不断地被调用,它将起作用,但是,它会降低性能,特别是如果ListView中有很多项目和视图时。

使用ViewHolder设计模式

现在,让我们看看它如何 ViewHolder模式一起使用。

  1. 第一次加载时,convertView为null。 我们将不得不增加列表项的布局,实例化ViewHolder,通过findViewById()找到TextView并将其分配给ViewHolder,然后将ViewHolder设置为convertView的标记。
  2. 第二次加载时,convertView不为null,很好! 我们不必再给它充气。 令人高兴的是,由于我们现在可以通过其ViewHolder访问TextView,因此不必调用findViewById()。
  3. 下次加载时,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商店应用的操作方式。

参考:The Ninja博客》中来自JCG合作伙伴 Mike Dalisay的Android ViewHolder模式示例

翻译自: https://www.javacodegeeks.com/2013/09/android-viewholder-pattern-example.html

viewholder

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ViewHolder 是用于提高 RecyclerView 性能的一个类,它可以缓存 ItemView 中的子控件,避免了频繁的 findViewById 操作。ViewHolder 的 XML 编写和普通的布局文件编写是一样的,只是在使用时需要将其与 RecyclerView.Adapter 中的 onCreateViewHolder 方法结合使用。 下面是一个简单的 ViewHolder 的 XML 编写示例: ```xml <!-- item_list.xml --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/item_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/item_image" /> <TextView android:id="@+id/item_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Item Name" /> <TextView android:id="@+id/item_description" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Item Description" /> </LinearLayout> ``` 在 RecyclerView.Adapter 中,我们需要重写 onCreateViewHolder 方法,实例化 ViewHolder 并将其与对应的布局文件绑定: ```java @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false); return new ViewHolder(view); } public class ViewHolder extends RecyclerView.ViewHolder { public ImageView imageView; public TextView nameView; public TextView descriptionView; public ViewHolder(View itemView) { super(itemView); imageView = itemView.findViewById(R.id.item_image); nameView = itemView.findViewById(R.id.item_name); descriptionView = itemView.findViewById(R.id.item_description); } } ``` 在这个例子中,ViewHolder 类中声明了三个子控件的变量,然后在构造函数中使用 findViewById 方法获取这些子控件的引用。这样,在 onBindViewHolder 方法中就可以直接使用这些子控件的引用,避免了频繁的 findViewById 操作,提高了 RecyclerView 的性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值