如何避免在Adapter类中多次调用findViewById()?

时间:2015-07-28 20:41:55

标签: android performance android-adapter findviewbyid

我试图通过在Adapter类中尽可能少地调用findViewById()来尽可能地加速应用程序。

我听说过一种“方式”,我可以在其中创建包含HashMap<T>实例和整数作为值的View,并将其与适配器的ViewHolder内部类一起使用。正如你所看到的,我对此一无所知,也没有机会就这种“方式”提出更多问题。

我一直在互联网上搜索解决方案,但我要么使用错误的关键字进行搜索,要么我不认识解决方案。

有人能以正确的方式指导我吗?也许有人在如何完成这个方面写了一小部分样本?

编辑1

我目前的ListView没有任何问题,因为它已经使用ViewHolder模式。这个问题的原因是因为我听说使用HashMap模式比使用ViewHolder模式实际上可以获得更快的速度。我知道这是模糊的描述,但这就是我来这里问的原因。

共享代码根本没用,因为它只是一个使用ViewHolder模式的常规适配器,就像您共享的链接中的那个一样。没有任何试验或使适配器变慢的东西。

再说一遍,问这个的主要原因是找到我们的模式是否比ViewHolder更快

2 个答案:

答案 0 :(得分:1)

减少对findViewById的调用的金额的方法是&#34; recycle&#34; ViewHolder的视图。背后的想法是保持膨胀的视图并在需要时重用它们 - 因为它们已经拥有ViewHolders,所以您不需要进行findViewById调用。

正如@nhaarman在他的回答的最后部分所描述的那样,为listview执行此操作的方法是在getView中重用convertView,如果它不为null并使用ViewHolder中引用的视图来更新它们。 / p>

first link提供的@nhaarman中描述了如何创建ViewHolder并将其存储在View by setTag中的方法。 然后在getView函数中,如果convertView不是null,则调用getTag以便返回ViewHolder。

在另一个注释中,您应该查看RecyclerView这是一个强制执行ViewHolder模式的列表视图。

答案 1 :(得分:1)

You should be using the ViewHolder paradigm which is most easily implemented with RecyclerView when Adapters are involved. Online sample code available here and GitHub sample cloneable via AndroidStudio directly or via Github.

The HashMap solution will work, but why incur a HashMap lookup when you can simply hold a reference to the object? Also, RecyclerView natively handles different View TYPEs so you don't have to roll your own solution when you have section header rows which look differently from data rows.

===============================================

A more detailed explanation of RecyclerView follows based on snippets from the sample I linked to.

Have your CustomAdapter extend RecyclerView.

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {

Create a Custom ViewHolder class. It should almost always be a static class if embedded within your CustomAdapter.

    public static class ViewHolder extends RecyclerView.ViewHolder {
        private final TextView textView;

        public ViewHolder(View v) {
            super(v);
            // Define click listener for the ViewHolder's View.
            v.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.d(TAG, "Element " + getPosition() + " clicked.");
                }
            });
            textView = (TextView) v.findViewById(R.id.textView);

Notice that the ViewHolder finds the views in the constructor since a ViewHolder instance is tied to a View instance. The ViewHolder should have references to any UI elements that you plan to update in an onBind callback. The ViewHolder object is then associated with the View by RecyclerView when you include the following code in your CustomAdapter.

// Create new views (invoked by the layout manager)
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
    // Create a new view.
    View v = LayoutInflater.from(viewGroup.getContext())
            .inflate(R.layout.text_row_item, viewGroup, false);

    return new ViewHolder(v);
}

Notice how the onCreateViewHolder callback is given a viewType parameter. The current code always returns the same type of custom ViewHolder, but it could be providing different ViewHolder classes based on the type (this is how you support rows that support different views). The following code is then how you update your UI when the view is bound to a dataset.

// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
    Log.d(TAG, "Element " + position + " set.");

    // Get element from your dataset at this position and replace the contents of the view
    // with that element
    viewHolder.getTextView().setText(mDataSet[position]);
}

With these pieces in place RecyclerView will create and reuse your Views AND ViewHolders by corresponding type reducing view hierarchy look ups and potentially making your app much less "janky".