Android recyclerView findViewHolderForAdapterPosition returns null

匿名 (未验证) 提交于 2019-12-03 03:04:01

问题:

I want to click an item in recyclerView programmatically, I found a way do that:

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

but it doesn't work for me, the findViewHolderForAdapterPosition just returns null.

Did I miss something in my code?

HistoryListAdapter:

public class HistoryListAdapter extends RecyclerView.Adapter { private static ArrayList recordItems; private static FragmentActivity activity; private static RecordList recordList;  public HistoryListAdapter(ArrayList 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(); 

I omitted some code, But it should not affect the overall structure of my code.

回答1:

According to the official documentation:

if notifyDataSetChanged() has been called but the new layout has not been calculated yet, this method will return null since the new positions of views are unknown until the layout is calculated.

It's not safe to use findViewHolderForAdapterPosition().

While you call this method after listView.swapAdapter(listadapter, false); you'll always get a null as result because notifyDataSetChanged() will be called.



回答2:

you can do this:

   listView.postDelayed(new Runnable()             {                 @Override                 public void run()                 {                     if(listView.findViewHolderForAdapterPosition(0)!=null )                     {                          listView.findViewHolderForAdapterPosition(0).itemView.performClick();                     }                 }             },50); 


回答3:

Hey I've solved the problem this way:

public class MyAdapter extends RecyclerView.Adapter {  private TextView mTotalSum; protected int mSum; protected ArrayList 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. Added ArrayList mViewholders field inside class
  2. added each viewholder instance to mViewHolders arraylist inside onBindSwipeViewHolder method
  3. used mViewholders arraylist instead of findViewHolderForadapterposition method inside setTotalSum method


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!