Android recyclelerView findViewHolderForAdapterPosition返回null

时间:2015-09-29 06:11:17

标签: android android-recyclerview

我想以编程方式单击recyclerView中的项目,我发现a way这样做:

recyclerView.findViewHolderForAdapterPosition(0).itemView.performClick();

但它对我不起作用,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);
    }
}
}

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();

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

7 个答案:

答案 0 :(得分:23)

根据official documentation

  

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

使用findViewHolderForAdapterPosition()是不安全的。

listView.swapAdapter(listadapter, false);之后调用此方法时,您将始终获得null因为notifyDataSetChanged()将被调用。

答案 1 :(得分:18)

你可以这样做:

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

                        listView.findViewHolderForAdapterPosition(0).itemView.performClick();
                    }
                }
            },50);

答案 2 :(得分:3)

我知道这已经很晚了,但可能对科特林时代的其他人有所帮助:

 binding.recycler.post {
     val view = binding.recycler.findViewHolderForAdapterPosition(position)?.itemView?.performClick()
 }

答案 3 :(得分:1)

您可以执行以下操作:

postAndNotifyAdapter(new Handler(),mRecyclerView);



protected void postAndNotifyAdapter(final Handler handler, final RecyclerView recyclerView) {
    handler.post(new Runnable() {
        @Override
        public void run() {
            if ( recyclerView.findViewHolderForLayoutPosition(0)!=null) {
                // This will call first item by calling "performClick()" of view.
                recyclerView.findViewHolderForLayoutPosition(0).itemView.performClick();
            } else {
                //   
                postAndNotifyAdapter(handler, recyclerView);
            }
        }
    });
}

答案 4 :(得分:0)

嘿,我用这种方式解决了这个问题:

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

private TextView mTotalSum;
protected int mSum;
protected ArrayList<BasketRVAdapter.ViewHolder> mViewHolders;

public BasketRVAdapter(JSONArray recyclerItems, Context context, TextView totalSum) {
    super(recyclerItems, context);
    mTotalSum = totalSum;
    mViewHolders = new ArrayList<>();
}

@Override
public RecyclerView.ViewHolder onCreateSwipeViewHolder(ViewGroup parent, int i) {
    View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.view_basket_rv_item, parent, true);

    return new ViewHolder(view);
}

@Override
public void onBindSwipeViewHolder(final RecyclerView.ViewHolder viewHolder, int position) {
    final BasketRVAdapter.ViewHolder holder = (BasketRVAdapter.ViewHolder) viewHolder;

    JSONObject object;
    try {
        object = mRecyclerItems.getJSONObject(position);
        final int priceValue = object.getInt("price");
        final int quantityValue = object.getInt("quantity");

        holder.setId(object.getInt("id"));
        holder.title.setText(object.getString("title"));
        holder.price.setText(String.format(mContext.getString(R.string.price), priceValue));
        holder.quantity.setText(String.valueOf(quantityValue));
        holder.sum.setText(String.valueOf(priceValue * quantityValue));

        holder.quantity.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void afterTextChanged(Editable editable) {
                String value = holder.quantity.getText().toString();

                if (value.equals("")) {
                    return;
                }

                if (value.equals("0")) {
                    Toast.makeText(mContext, R.string.null_value_error, Toast.LENGTH_SHORT).show();
                    return;
                }
                holder.sum.setText(String.valueOf(priceValue * Integer.valueOf(value)));
                setTotalSum();
            }

        });

        mViewHolders.add(holder);
        mSum += priceValue * quantityValue;

        if (position == getItemCount() - 1) {
            mTotalSum.setText(String.format(mContext.getString(R.string.total_sum), mSum));
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

@Override
public SwipeConfiguration onCreateSwipeConfiguration(Context context, int i) {
    return new SwipeConfiguration.Builder(context)
                                 .setLeftSwipeBehaviour(SwipeConfiguration.SwipeBehaviour.NORMAL_SWIPE)
                                 .setRightSwipeBehaviour(SwipeConfiguration.SwipeBehaviour.NO_SWIPE)
                                 .setLeftBackgroundColorResource(R.color.dt_basket_deleted)
                                 .setLeftUndoDescription(R.string.deleted)
                                 .setDescriptionTextColorResource(R.color.dt_white)
                                 .setLeftUndoable(true)
                                 .build();
}

@Override
public void onSwipe(int i, int i1, RecyclerView.ViewHolder holder) {
    try {
        if (i1 == SWIPE_LEFT) {
            remove(i);
            notifyItemRemoved(i);
            mViewHolders.remove(i);
            setTotalSum();
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

public int getSum() {
    return mSum;
}

public void setTotalSum() {
    int totalSum = 0;

    for (BasketRVAdapter.ViewHolder holder : mViewHolders) {
        totalSum += Integer.valueOf(holder.sum.getText().toString());
    }

    mSum = totalSum;
    mTotalSum.setText(String.format(mContext.getString(R.string.total_sum), totalSum));
}

public static class ViewHolder extends RecyclerView.ViewHolder {

    @Bind(R.id.trade_title)
    public TextView title;
    @Bind(R.id.trade_price)
    public TextView price;
    @Bind(R.id.trade_quantity)
    public EditText quantity;
    @Bind(R.id.sum)
    public TextView sum;

    private int mId;

    public ViewHolder(View itemView) {
        super(itemView);
        ButterKnife.bind(this, itemView);
    }

    public int getId() {
        return mId;
    }

    public void setId(int id) {
        mId = id;
    }
}}
  1. 在类
  2. 中添加了ArrayList mViewholders字段
  3. 将每个视图实例添加到onBindSwipeViewHolder方法内的mViewHolders arraylist
  4. 在setTotalSum方法中使用mViewholders arraylist而不是findViewHolderForadapterposition方法

答案 5 :(得分:0)

我不建议使用发布延迟。尽管可以,但时间是任意的。

在recyclerview上使用OnPreDrawListener,时间将与下一个绘制周期对齐,并且可以访问可见项。

答案 6 :(得分:0)

你应该使用 recyclerview.findViewHolderForLayoutPosition(position)