Android recyclelerView findViewHolderForAdapterPosition返回null

Aar*_*sai 19 android android-recyclerview

我想以编程方式单击recyclerView中的项目,我找到了一种方法:

recyclerView.findViewHolderForAdapterPosition(0).itemView.performClick();
Run Code Online (Sandbox Code Playgroud)

但它对我不起作用,findViewHolderForAdapterPosition只返回null.

我在代码中遗漏了什么吗?

HistoryListAdapter:

public class HistoryListAdapter extends RecyclerView.Adapter<HistoryListAdapter.ViewHolder> {
private static ArrayList<RecordItem> recordItems;
private static FragmentActivity activity;
private static RecordList recordList;

public HistoryListAdapter(ArrayList<RecordItem> recordItems, FragmentActivity FA, RecordList FRL) {
    this.recordItems = recordItems;
    this.activity = FA;
    this.recordList = FRL;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    // create a new view
    View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.recorditem, parent, false);
    return new ViewHolder(itemLayoutView);
}

@Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
    // TextView setText ...
}

// Return the size of the itemsData (invoked by the layout manager)
@Override
public int getItemCount() {
    return recordItems.size();
}

// inner class to hold a reference to each item of RecyclerView
public static class ViewHolder extends RecyclerView.ViewHolder{
    public TextView result, datetime;

    public ViewHolder(View itemLayoutView) {
        super(itemLayoutView);
        itemLayoutView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (activity != null) {
                    // do something...
                }
            }
        });
        result = (TextView) itemLayoutView.findViewById(R.id.result);
        heartrate = (TextView) itemLayoutView.findViewById(R.id.heartrate);
        datetime = (TextView) itemLayoutView.findViewById(R.id.datetime);
    }
}
}
Run Code Online (Sandbox Code Playgroud)

RecordList:

RecyclerView listView = (RecyclerView) layoutView.findViewById(R.id.listView);
HistoryListAdapter listadapter = new HistoryListAdapter(itemsToShow, getActivity(), RecordList.this);
listView.swapAdapter(listadapter, false);
listView.findViewHolderForAdapterPosition(0).itemView.performClick();
Run Code Online (Sandbox Code Playgroud)

我省略了一些代码,但它不应该影响我的代码的整体结构.

Ram*_*ami 26

根据官方文件:

如果已调用notifyDataSetChanged()但尚未计算新布局,则此方法将返回null,因为在计算布局之前,视图的新位置未知.

这是不安全的使用findViewHolderForAdapterPosition().

当你listView.swapAdapter(listadapter, false);总是得到一个null结果因为notifyDataSetChanged()将被调用之后你调用这个方法.

  • 而你没有给出任何解决这个问题的答案,为什么呢?你刚刚说它不行……嗯……我们都已经发现了 (14认同)
  • 那要用什么?@Rami (3认同)
  • @eric是一个不好的做法来管理适配器外的viewHolder. (2认同)
  • 在notifyDataSetChanged之后可以使用recyclerView.post()方法。 (2认同)
  • 这个答案并没有给出问题的任何解决方案。 (2认同)

Dha*_*raj 20

你可以这样做:

   listView.postDelayed(new Runnable()
            {
                @Override
                public void run()
                {
                    if(listView.findViewHolderForAdapterPosition(0)!=null )
                    {

                        listView.findViewHolderForAdapterPosition(0).itemView.performClick();
                    }
                }
            },50);
Run Code Online (Sandbox Code Playgroud)

  • 永远不要这样做。您确定 50 毫秒对于旧设备和速度较慢的设备是否足够?每当你在那里看到`postDelayed` 时忽略答案(这不仅仅是关于这个问题,我已经看到很多类似的答案和对其他问题的评论)。这很傻... (7认同)
  • @user25虽然我明白你来自哪里,但在这种情况下调用`Handler.post()`即使没有延迟也可以工作,因为它会将抓取`ViewHolder`的任务放在UI线程队列的末尾,因此该任务将在 UI 设置“RecyclerView”及其“ViewHolder”等之后调用。 (2认同)

Ale*_*gos 5

我知道这已经很晚了,但也许对 Kotlin 时代的其他人有帮助:

 binding.recycler.post {
     val view = binding.recycler.findViewHolderForAdapterPosition(position)?.itemView?.performClick()
 }
Run Code Online (Sandbox Code Playgroud)