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

ber*_*r77 5 android textview recycler-adapter android-recyclerview

我有一个VerticalGridView正在使用RecyclerView.Adapter填充元素。我发现onBindViewHolder()如果潜在元素不在视口中,则不会调用该方法。不幸的是,这是NullPointerException由另一种方法引起的,因为我TextView在该onBindViewHolder()方法中捕获了一个引用并将其传递给外部变量以供以后操作。

@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;
                }
            }

        }
    });
Run Code Online (Sandbox Code Playgroud)

据我了解,实例化对象TextView时会创建对gets 的引用Viewholder

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

实例化onBindViewHolder()时,是否有一种方法可以强制在所有元素上至少调用一次Adapter

我尝试了这里的建议但没有成功。

我了解到,强制onBindViewHolder()所有元素都将违反RecycleView.Adapter整个目的。因此,我愿意就如何获得该TextView参考意见提出其他建议。

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

ber*_*r77 6

解决此问题的最简单的解决方案是向下滚动到网格底部,然后返回到顶部。但这无法在该方法中完成,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);
}
Run Code Online (Sandbox Code Playgroud)

这是一个很好的解决方案尝试,但不幸的是它仍然不起作用。虽然它确实获得了使该方法起作用的参考,但它不一定具有正确的参考。我发现引用最终可能指向不同的 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()));
}
Run Code Online (Sandbox Code Playgroud)

我还更改了我的数据对象,使其保存一个 int 值而不是对 the 的引用,TextView因为上面证明了该引用无效。最后,Adapter当我按下自定义后退按钮时,我添加了一个呼叫。

grids.get(0).getAdapter().notifyDataSetChanged();
Run Code Online (Sandbox Code Playgroud)

感谢所有贡献者!