如何强制RecyclerView.Adapter在所有元素上调用onBindViewHolder()

我有一个VerticalGridView,它使用RecyclerView.Adapter来填充元素.我发现如果潜在元素不在视口范围内,则不会调用onBindViewHolder()方法.不幸的是,这导致了另一个方法的NullPointerException异常,因为我在onBindViewHolder()方法中捕获了TextView引用,并将其传递给外部变量以供以后使用.

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    final ViewHolder viewHolder = (ViewHolder) holder;
    viewHolder.txtCategoryName.setText(categories.get(position).getStrCategory());
    categories.get(position).setTxtViewReference(viewHolder.txtCategoryDefectTotal);
    viewHolder.categoryBoxRoot.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            for(CategoryListItem catItem : categories){
                if(catItem.getStrCategory().equals(viewHolder.txtCategoryName.getText())){
                    int index = Defects.getInstance().getCategories().indexOf(catItem) + 1;
                    MainInterface.grids.get(index).bringToFront();
                    MainInterface.grids.get(index).setVisibility(View.VISIBLE);
                    for(VerticalGridView grid : MainInterface.grids){
                        int gridIndex = MainInterface.grids.indexOf(grid);
                        if(gridIndex != index){
                            grid.setVisibility(View.INVISIBLE);
                        }
                    }
                    break;
                }
            }

        }
    });

据我了解,当实例化Viewholder对象时,将创建对TextView的引用.

public class ViewHolder extends RecyclerView.ViewHolder {

    public TextView txtCategoryName;
    public TextView txtCategoryDefectTotal;
    public View categoryBoxRoot;

    public ViewHolder(View itemView) {
        super(itemView);
        txtCategoryName = (TextView) itemView.findViewById(R.id.textViewCategoryName);
        txtCategoryDefectTotal = (TextView) itemView.findViewById(R.id.textViewCategoryTotalDefects);
        categoryBoxRoot = itemView.findViewById(R.id.root_category_box);
    }
}

有没有一种方法可以在实例化适配器时强制在所有元素上至少一次调用onBindViewHolder()?

我尝试了here的建议,但没有成功.

我知道在所有元素上强制onBindViewHolder()都可以与whole purpose of the RecycleView.Adapter配合使用.因此,对于如何捕获该TextView引用,我持开放态度.

作为此问题的临时解决方案,我可以在生成NullPointerException的方法周围使用try catch块.但是,我担心缺少参考资料意味着我将来可能会引入错误.

解决方法:

解决此问题的最简单方法是向下滚动到网格底部,然后再向上滚动至顶部.尽管无法在onCreate()方法中完成此操作,因为当时该网格在技术上不可见.而是应在活动的onResume()方法中调用它.

@Override
public void onResume(){
    super.onResume();
    VerticalGridView defectGrid = grids.get(0);
    RecyclerView.Adapter adapter = defectGrid.getAdapter();
    defectGrid.smoothScrollToPosition(adapter.getItemCount()-1);
    defectGrid.smoothScrollToPosition(0);
}

这是解决问题的一种很好的尝试,但是不幸的是,它仍然行不通.尽管它确实获得了使该方法起作用的参考,但它不一定具有正确的参考.我发现该引用最终可能指向不同的TextView,因为RecycleView.Adapter重用视图以在不同区域显示它们.

解:

马克·基恩(Mark Keen)说使用notifyDataSetChanged()是正确的.我通过修复onBindViewHolder()方法使其正常工作来使其工作.

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    final ViewHolder viewHolder = (ViewHolder) holder;
    viewHolder.txtCategoryName.setText(categories.get(position).getStrCategory());
    viewHolder.txtCategoryDefectTotal.setText(String.valueOf(categories.get(position).getTotalDefectsInCategory()));
}

我还更改了我的数据对象,因此它持有一个int值,而不是对TextView的引用,因为以上内容证明了该引用无效.最后,当我按下自定义后退按钮时,我向适配器添加了一个呼叫.

grids.get(0).getAdapter().notifyDataSetChanged();

谢谢大家的贡献!

上一篇:渲染问题找不到以下类-android.support.v7.widget.AppCompatTextView


下一篇:我在字体家族Android Studio中找不到sans-serif-medium