简体   繁体   English

Android RecyclerView items shuffles on scroll

[英]Android RecyclerView items shuffles on scroll

Items/cells of my multiple view type RecyclerView Adapter get shuffles on the scroll.我的多视图类型 RecyclerView 适配器的项目/单元格在滚动上随机播放。 I go through all below possible solutions but none of them working.我通过以下所有可能的解决方案 go 但没有一个工作。

1. 1.

@Override
public long getItemId(int position) {
   return mDataset.get(position).hashCode();
   or
   return mDataset.get(position).getBaseFormElementId();
}

setHasStableIds(true);
  1. Increased the cache of RecyclerView增加了 RecyclerView 的缓存

Please share if anyone has any solution.如果有人有任何解决方案,请分享。

My Adapter Class我的适配器 Class

public class FormAdapter extends RecyclerView.Adapter<BaseViewHolder>  {

private Context mContext;
private List<BaseFormElement> mDataset;


public FormAdapter(Context context) {
    mContext = context;
    mDataset = new ArrayList<>();
    setHasStableIds(true);
 }



public List<BaseFormElement> getDataset() {
    return mDataset;
}


public OnFormElementValueChangedListener getValueChangeListener() {
    return mListener;
}


@Override
public int getItemCount() {
    return mDataset.size();
}


@Override
public int getItemViewType(int position) {
    return mDataset.get(position).getType();
}

@Override
public long getItemId(int position) {
    //return super.getItemId(position);

    return mDataset.get(position).getBaseFormElementId();
}


@NonNull
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    // get layout based on header or element type
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    View v;
    switch (viewType) {
        case BaseFormElement.TYPE_HEADER:
            v = inflater.inflate(R.layout.form_element_header, parent, false);
            return new FormElementHeader(v);
        case BaseFormElement.TYPE_EDIT_TEXT:
            v = inflater.inflate(R.layout.form_element, parent, false);
            return new FormElementEditTextViewHolder(v, new FormItemEditTextListener(this));
        case BaseFormElement.TYPE_PICKER_DATE:
            v = inflater.inflate(R.layout.form_element, parent, false);
            return new FormElementPickerDateViewHolder(v, mContext, this);
        case BaseFormElement.TYPE_PICKER_TIME:
            v = inflater.inflate(R.layout.form_element, parent, false);
            return new FormElementPickerTimeViewHolder(v, mContext, this);
        case BaseFormElement.TYPE_PICKER_SINGLE:
            v = inflater.inflate(R.layout.form_element, parent, false);
            return new FormElementPickerSingleViewHolder(v, mContext, this, new FormItemEditTextListener(this));
        case BaseFormElement.TYPE_PICKER_MULTI:
            v = inflater.inflate(R.layout.formelementlabel, parent, false);
            return new FormElementPickerMultiViewHolder(v, mContext, this);
        case BaseFormElement.TYPE_IMAGE_REMARKS:
            v = inflater.inflate(R.layout.formelementlabel, parent, false);
            return new FormElementImageWithRemarksViewHolder(v, mContext, this);
        case BaseFormElement.TYPE_SWITCH:
            v = inflater.inflate(R.layout.form_element_switch, parent, false);
            return new FormElementSwitchViewHolder(v, mContext, this);
        case BaseFormElement.TYPE_SEGMENT:
            v = inflater.inflate(R.layout.form_element_switch, parent, false);
            return new FormElementSwitchViewHolder(v, mContext, this);
        case BaseFormElement.TYPE_LABEL:
            v = inflater.inflate(R.layout.formelementlabel, parent, false);
            return new FormElementLabelViewHolder(v, clicklistner);
        case BaseFormElement.TYPE_IMAGE:
            v = inflater.inflate(R.layout.formelementlabel, parent, false);
            return new FromElementImageViewHolder(v, mContext, this);
        case BaseFormElement.TYPE_VIDEO:
            v = inflater.inflate(R.layout.formelementlabel, parent, false);
            return new FormElementVideoViewHolder(v, mContext, this);
        case BaseFormElement.DIALOG_LIST:
            v = inflater.inflate(R.layout.form_element_mmv, parent, false);
            return new FormElementDialogListViewHolder(v, mContext, this);
        case BaseFormElement.TYPE_SLIDER:
            v = inflater.inflate(R.layout.formelementlabel, parent, false);
            return new FormElementSliderViewHolder(v, mContext, this);
        default:
            v = inflater.inflate(R.layout.form_element, parent, false);
            return new FormElementEditTextViewHolder(v, new FormItemEditTextListener(this));
    }
}


@Override
public void onBindViewHolder(BaseViewHolder holder, final int position) {
    // gets current object
    BaseFormElement currentObject = mDataset.get(position);
    holder.bind(position, currentObject, mContext);
}

} }

I have worked on this type of RecyclerView and here is the DynamicAdapter class used with multiple view-type .我研究过这种类型的RecyclerView ,这里是DynamicAdapter class 与多view-type一起使用。 I hope you get some clarity on how to use it.我希望您对如何使用它有所了解。

    public class DynamicAdapter extends RecyclerView.Adapter <BaseViewHolder> {

  private static final String TAG = "DynamicAdapter";
  private static final int VIEW_EMPTY = 0;
  private static final int VIEW_EDIT_TEXT = 1;
  private static final int VIEW_SIGNATURE = 2;
  private static final int VIEW_UPLOAD = 3;
  private static final int VIEW_DATE_TIME = 4;
  private static final int VIEW_DATE_RANGE = 5;
  private static final int VIEW_DATE = 6;
  private static final int VIEW_DESCRIPTION = 7;
  private static final int VIEW_UNDEFINED = 8;

  ArrayList <FormData> formDataList;
  private Context context;
  private AdapterListener adapterListener;

  public DynamicAdapter(ArrayList <FormData > formDataList) {
   this.formDataList = formDataList;
  }

  public void setAdapterListener(AdapterListener adapterListener) {
   this.adapterListener = adapterListener;
  }
  @NonNull
  @Override
  public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
   this.context = parent.getContext();
   switch (viewType) {
    case VIEW_EDIT_TEXT:
     ItemDynamicFormEdittextBinding edittextBinding = ItemDynamicFormEdittextBinding
      .inflate(LayoutInflater.from(parent.getContext()), parent, false);
     return new EditTextViewHolder(edittextBinding);
    case VIEW_NUMBER:
     ItemDynamicFormNumberBinding numberBinding = ItemDynamicFormNumberBinding
      .inflate(LayoutInflater.from(parent.getContext()), parent, false);
     return new NumberViewHolder(numberBinding);
    case VIEW_EMAIL:
     ItemDynamicFormEmailBinding emailBinding = ItemDynamicFormEmailBinding
      .inflate(LayoutInflater.from(parent.getContext()), parent, false);
     return new EmailViewHolder(emailBinding);
    case VIEW_UPLOAD:
     ItemDynamicFormUploadBinding uploadBinding = ItemDynamicFormUploadBinding
      .inflate(LayoutInflater.from(parent.getContext()), parent, false);
     return new UploadViewHolder(uploadBinding);
    case VIEW_DATE_RANGE:
     ItemDynamicFormDateRangeBinding rangeBinding = ItemDynamicFormDateRangeBinding
      .inflate(LayoutInflater.from(parent.getContext()), parent, false);
     return new DateRangeViewHolder(rangeBinding);
    case VIEW_DATE_TIME:
     ItemDynamicFormDateTimeBinding dateTimeBinding = ItemDynamicFormDateTimeBinding
      .inflate(LayoutInflater.from(parent.getContext()), parent, false);
     return new DateTimeViewHolder(dateTimeBinding);
    case VIEW_DATE:
     ItemDynamicFormDateBinding dateBinding = ItemDynamicFormDateBinding
      .inflate(LayoutInflater.from(parent.getContext()), parent, false);
     return new DateViewHolder(dateBinding);
    case VIEW_DESCRIPTION:
     ItemDynamicFormDescriptionBinding descriptionBinding = ItemDynamicFormDescriptionBinding
      .inflate(LayoutInflater.from(parent.getContext()), parent, false);
     return new DescriptionViewHolder(descriptionBinding);
    case VIEW_UNDEFINED:
     ItemDynamicFormUnknownBinding unknownBinding = ItemDynamicFormUnknownBinding
      .inflate(LayoutInflater.from(parent.getContext()), parent, false);
     return new UnknownViewHolder(unknownBinding);
    default:
     ItemDynamicFormEmptyViewBinding emptyViewBinding = ItemDynamicFormEmptyViewBinding
      .inflate(LayoutInflater.from(parent.getContext()), parent, false);
     return new EmptyViewHolder(emptyViewBinding);
   }
  }
  @Override
  public void onBindViewHolder(@NonNull BaseViewHolder holder, final int position) {
   holder.onBind(position);
  }

  @Override
  public int getItemCount() {
   return formDataList.size();
  }

  @Override
  public int getItemViewType(int position) {
   if (formDataList != null && !formDataList.isEmpty()) {
    if (formDataList.get(position) != null &&
     formDataList.get(position).getType() != null) {
     switch (formDataList.get(position).getType()) {
      case TEXT:
       return VIEW_EDIT_TEXT;
      case CAMERA:
       return VIEW_CAMERA;
      case TOGGLE:
       return VIEW_TOGGLE;
      case NUMBER:
       return VIEW_NUMBER;
      case EMAIL:
       return VIEW_EMAIL;
      case DATE_RANGE:
       return VIEW_DATE_RANGE;
      case DATE_TIME:
       return VIEW_DATE_TIME;
      default:
       return VIEW_UNDEFINED;
     }
    } else {
     return VIEW_UNDEFINED;
    }
   } else {
    return VIEW_EMPTY;
   }
  }

  /**
   * Class used to handle all the text fields for email,text & number.
   */
  private class EditTextViewHolder extends BaseViewHolder {

   ItemDynamicFormEdittextBinding mBinding;

   EditTextViewHolder(ItemDynamicFormEdittextBinding binding) {
    super(binding.getRoot());
    Log.e(TAG, "EditTextViewHolder: ------------>>");
    this.mBinding = binding;
    mBinding.edDynamicFormText.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) {
      formDataList.get(getAdapterPosition()).setEnteredValue(charSequence.toString());
     }

     @Override
     public void afterTextChanged(Editable editable) {

     }
    });
   }

   @Override
   public void onBind(int position) {
    final FormData formData = formDataList.get(position);
    FormEdittextViewModel emptyItemViewModel = new FormEdittextViewModel(formData);
    mBinding.setViewModel(emptyItemViewModel);

    // Immediate Binding
    // When a variable or observable changes, the binding will be scheduled to change before
    // the next frame. There are times, however, when binding must be executed immediately.
    // To force execution, use the executePendingBindings() method.
    mBinding.executePendingBindings();
   }
  }

  /**
   * Class used to handle all the text fields for email, text & number.
   */
  private class NumberViewHolder extends BaseViewHolder {

   ItemDynamicFormNumberBinding mBinding;

   NumberViewHolder(ItemDynamicFormNumberBinding binding) {
    super(binding.getRoot());
    this.mBinding = binding;

    mBinding.edDynamicFormNumber.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) {
      formDataList.get(getAdapterPosition()).setEnteredValue(charSequence.toString());
     }

     @Override
     public void afterTextChanged(Editable editable) {

     }
    });
   }

   @Override
   public void onBind(int position) {
    final FormData formData = formDataList.get(position);
    mBinding.setViewModel(new FormNumberViewModel(formData));
    // Immediate Binding
    // When a variable or observable changes, the binding will be scheduled to change before
    // the next frame. There are times, however, when binding must be executed immediately.
    // To force execution, use the executePendingBindings() method.
    mBinding.executePendingBindings();
   }
  }

  /**
   * Class used to handle all the text fields for email, text & number.
   */
  private class EmailViewHolder extends BaseViewHolder {

   ItemDynamicFormEmailBinding mBinding;

   EmailViewHolder(ItemDynamicFormEmailBinding binding) {
    super(binding.getRoot());
    this.mBinding = binding;
    mBinding.edDynamicFormEmail.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) {
      formDataList.get(getAdapterPosition()).setEnteredValue(charSequence.toString());
     }

     @Override
     public void afterTextChanged(Editable editable) {

     }
    });
   }

   @Override
   public void onBind(int position) {
    final FormData formData = formDataList.get(position);

    //val radioButton = mBinding.root.findViewById(R.id.radioButtton) as RadioButton
    FormEmailViewModel emptyItemViewModel = new FormEmailViewModel(formData);
    mBinding.setViewModel(emptyItemViewModel);

    // Immediate Binding
    // When a variable or observable changes, the binding will be scheduled to change before
    // the next frame. There are times, however, when binding must be executed immediately.
    // To force execution, use the executePendingBindings() method.
    mBinding.executePendingBindings();
   }
  }

  /**
   * Class used to handle all the text fields for description only.
   */
  private class DescriptionViewHolder extends BaseViewHolder {

   ItemDynamicFormDescriptionBinding mBinding;

   DescriptionViewHolder(ItemDynamicFormDescriptionBinding binding) {
    super(binding.getRoot());
    this.mBinding = binding;
    mBinding.edDynamicFormDesc.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) {
      formDataList.get(getAdapterPosition()).setEnteredValue(charSequence.toString());
     }

     @Override
     public void afterTextChanged(Editable editable) {

     }
    });
   }

   @Override
   public void onBind(int position) {
    final FormData formData = formDataList.get(position);

    FormDescriptionViewModel emptyItemViewModel = new FormDescriptionViewModel(formData);
    mBinding.setViewModel(emptyItemViewModel);

    // Immediate Binding
    // When a variable or observable changes, the binding will be scheduled to change before
    // the next frame. There are times, however, when binding must be executed immediately.
    // To force execution, use the executePendingBindings() method.
    mBinding.executePendingBindings();
   }
  }
  /**
   * Class used to select pic form device and upload to server.
   */
  private class UploadViewHolder extends BaseViewHolder
  implements FormUploadViewModel.UploadListener {
   private ItemDynamicFormUploadBinding mBinding;

   private UploadViewHolder(ItemDynamicFormUploadBinding mBinding) {
    super(mBinding.getRoot());
    this.mBinding = mBinding;
   }

   @Override
   public void onBind(int position) {
    final FormData data = formDataList.get(position);

    FormUploadViewModel uploadViewModel = new FormUploadViewModel(data, this);
    mBinding.setViewModel(uploadViewModel);
    // Immediate Binding
    // When a variable or observable changes, the binding will be scheduled to change before
    // the next frame. There are times, however, when binding must be executed immediately.
    // To force execution, use the executePendingBindings() method.
    mBinding.executePendingBindings();
   }

   @Override
   public void onUploadClick(@NonNull FormData formData) {
    adapterListener.onUploadPic(getAdapterPosition(), formData);
   }
  }

  /**
   * Class used to pick date and time.
   */
  private class DateTimeViewHolder extends BaseViewHolder
  implements FormDateTimeViewModel.DateTimeListener {

   ItemDynamicFormDateTimeBinding mBinding;
   int mYear;
   int mMonth;
   int mDay;
   int mHour;
   int mMinute;
   int mSecond;
   FormDateTimeViewModel dateTimeViewModel;
   FormData data;

   DateTimeViewHolder(ItemDynamicFormDateTimeBinding mBinding) {
    super(mBinding.getRoot());
    this.mBinding = mBinding;
   }

   @Override
   public void onBind(int position) {
    data = formDataList.get(position);
    dateTimeViewModel = new FormDateTimeViewModel(data, this);
    mBinding.setViewModel(dateTimeViewModel);
    // Immediate Binding
    // When a variable or observable changes, the binding will be scheduled to change before
    // the next frame. There are times, however, when binding must be executed immediately.
    // To force execution, use the executePendingBindings() method.
    mBinding.executePendingBindings();
   }

   @Override
   public void dateClick() {
    Calendar calendar = Calendar.getInstance();
    mHour = calendar.get(Calendar.HOUR_OF_DAY);
    mMinute = calendar.get(Calendar.MINUTE);
    mSecond = 0;
    mYear = calendar.get(Calendar.YEAR);
    mMonth = calendar.get(Calendar.MONTH);
    mDay = calendar.get(Calendar.DAY_OF_MONTH);
    CommonUtils.openDatePicker(context, mYear, mMonth, mDay,
     0, 0, (view, year, monthOfYear, dayOfMonth) -> {
      String selectedDate = dayOfMonth + "-" + (monthOfYear + 1) + "-" + year;
      Calendar cal = Calendar.getInstance();
      cal.set(Calendar.YEAR, year);
      cal.set(Calendar.MONTH, monthOfYear);
      cal.set(Calendar.DAY_OF_MONTH, dayOfMonth);
      /*cal.set(Calendar.HOUR_OF_DAY, mHour);
      cal.set(Calendar.MINUTE, mMinute);
      cal.set(Calendar.SECOND, 0);*/

      dateTimeViewModel.getDate().set(DateTimeUtil.getParsedDate(cal.getTimeInMillis()));
      data.setEnteredValue(cal.getTimeInMillis() + "");
     });
   }

   @Override
   public void timeClick() {
    Calendar calendar = Calendar.getInstance();
    mHour = calendar.get(Calendar.HOUR_OF_DAY);
    mMinute = calendar.get(Calendar.MINUTE);

    CommonUtils.openTimePicker(context, mHour, mMinute,
     (view, hourOfDay, minute) -> {

      Calendar cal = Calendar.getInstance();
      cal.set(Calendar.YEAR, mYear);
      cal.set(Calendar.MONTH, mMonth);
      cal.set(Calendar.DAY_OF_MONTH, mDay);
      cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
      cal.set(Calendar.MINUTE, minute);
      cal.set(Calendar.SECOND, 0);
      dateTimeViewModel.getTime().set(DateTimeUtil.getParsedTime(cal.getTimeInMillis()));
      data.setEnteredValue(cal.getTimeInMillis() + "");
     });
   }
  }

  /**
   * Class used to pick date from & to .
   */
  private class DateRangeViewHolder extends BaseViewHolder
  implements FormDateRangeViewModel.DateRangeListener {
   ItemDynamicFormDateRangeBinding mBinding;
   FormDateRangeViewModel uploadViewModel;

   DateRangeViewHolder(ItemDynamicFormDateRangeBinding mBinding) {
    super(mBinding.getRoot());
    this.mBinding = mBinding;
   }

   @Override
   public void onBind(int position) {
    FormData data = formDataList.get(position);

    uploadViewModel = new FormDateRangeViewModel(data, this);
    mBinding.setViewModel(uploadViewModel);
    // Immediate Binding
    // When a variable or observable changes, the binding will be scheduled to change before
    // the next frame. There are times, however, when binding must be executed immediately.
    // To force execution, use the executePendingBindings() method.
    mBinding.executePendingBindings();
   }

   @Override
   public void dateViewClick(@NotNull View view) {
    // Get Current Date
    Calendar c = Calendar.getInstance();
    int mYear = c.get(Calendar.YEAR);
    int mMonth = c.get(Calendar.MONTH);
    int mDay = c.get(Calendar.DAY_OF_MONTH);
    //            int mHour = c.get(Calendar.HOUR_OF_DAY);
    //            int mMin = c.get(Calendar.MINUTE);
    CommonUtils.openDatePicker(context, mYear, mMonth, mDay,
     c.getTimeInMillis(), 0, (view1, year, monthOfYear, dayOfMonth) -> {
      //String selectedDate = dayOfMonth + "-" + (monthOfYear + 1) + "-" + year;
      Calendar cal = Calendar.getInstance();
      cal.set(Calendar.YEAR, year);
      cal.set(Calendar.MONTH, monthOfYear);
      cal.set(Calendar.DAY_OF_MONTH, dayOfMonth);

      switch (view.getId()) {
       case R.id.tvDateRange1:
        uploadViewModel.getDate1().set(DateTimeUtil.getParsedDate(cal.getTimeInMillis()));
        formDataList.get(getAdapterPosition()).setMaxRange(cal.getTimeInMillis());
        break;
       case R.id.tvDateRange2:
        uploadViewModel.getDate2().set(DateTimeUtil.getParsedDate(cal.getTimeInMillis()));
        formDataList.get(getAdapterPosition()).setMinRange(cal.getTimeInMillis());
        break;
      }
     });

   }
  }

  /**
   * Class used to pick date
   */
  private class DateViewHolder extends BaseViewHolder
  implements FormDateViewModel.DateListener {
   ItemDynamicFormDateBinding mBinding;
   FormDateViewModel emptyItemViewModel;
   int mYear, mMonth, mDay;

   DateViewHolder(ItemDynamicFormDateBinding mBinding) {
    super(mBinding.getRoot());
    this.mBinding = mBinding;
   }

   @Override
   public void onBind(int position) {
    FormData data = formDataList.get(position);

    emptyItemViewModel = new FormDateViewModel(data, this);
    mBinding.setViewModel(emptyItemViewModel);
    // Immediate Binding
    // When a variable or observable changes, the binding will be scheduled to change before
    // the next frame. There are times, however, when binding must be executed immediately.
    // To force execution, use the executePendingBindings() method.
    mBinding.executePendingBindings();
   }

   @Override
   public void onDateClick() {
    Calendar calendar = Calendar.getInstance();
    mYear = calendar.get(Calendar.YEAR);
    mMonth = calendar.get(Calendar.MONTH);
    mDay = calendar.get(Calendar.DAY_OF_MONTH);
    CommonUtils.openDatePicker(context, mYear, mMonth, mDay,
     0, 0, (view, year, monthOfYear, dayOfMonth) -> {
      //                        String selectedDate = dayOfMonth + "-" + (monthOfYear + 1) + "-" + year;

      Calendar c = Calendar.getInstance();
      c.set(Calendar.YEAR, year);
      c.set(Calendar.MONTH, monthOfYear);
      c.set(Calendar.DAY_OF_MONTH, dayOfMonth);
      formDataList.get(getAdapterPosition()).setMaxRange(c.getTimeInMillis());
      emptyItemViewModel.getDate().set(DateTimeUtil.getParsedDate(c.getTimeInMillis()));

     });
   }
  }

/**
 * If hashMap is empty show empty view
 */
private class EmptyViewHolder extends BaseViewHolder
        implements FormEmptyItemViewModel.ClickListener {

    private ItemDynamicFormEmptyViewBinding mBinding;

    EmptyViewHolder(ItemDynamicFormEmptyViewBinding binding) {
        super(binding.getRoot());
        this.mBinding = binding;
    }

    @Override
    public void onBind(int position) {
        FormEmptyItemViewModel emptyItemViewModel = new FormEmptyItemViewModel(this);
        mBinding.setViewModel(emptyItemViewModel);
    }
}

/**
 * If view type is not handled then show this view
 */
private class UnknownViewHolder extends BaseViewHolder {

    UnknownViewHolder(ItemDynamicFormUnknownBinding unknownBinding) {
        super(unknownBinding.getRoot());
    }

    @Override
    public void onBind(int position) {

    }
}

If you have any doubt let me know, Happy Coding:)如果您有任何疑问,请告诉我,Happy Coding:)

Make the RecyclerView ViewModel non-recyclable.使 RecyclerView ViewModel 不可回收。 I think the recyclerview is set to refresh by default, therefore, shuffling the items For example我认为recyclerview默认设置为刷新,因此,打乱项目例如

class YourViewModel extends RecyclerView.ViewHolder {

    YourViewModel (@NonNull View view) {
       super(view);

       // Add the line below
       this.setIsRecyclable(false);

     }
}

Also, you could implement a sorting method using Collection.sort(items) before the items are populated, so even when the view gets recycled, the items still remain sorted (eg. by id).此外,您可以在填充项目之前使用 Collection.sort(items) 实现排序方法,因此即使视图被回收,项目仍然保持排序(例如按 id)。

You may try:你可以试试:

@Override
public long getItemId(int position) {
    return position;
}

Also override:同时覆盖:

@Override
public int getItemViewType(int position) {
    return position;
}

One way to increase the cache for recyclerview is:为 recyclerview 增加缓存的一种方法是:

recyclerView.setItemViewCacheSize(20)

You can also get extra space with the help of LinearLayoutManager's method calculateExtraLayoutSpace .您还可以借助 LinearLayoutManager 的方法calculateExtraLayoutSpace获得额外空间。 I've added links to the docs.我已经添加了文档的链接。

Alternatively you can use:或者,您可以使用:

setIsRecyclable(false);

But it beats the purpose of using RecyclerView.但这超出了使用 RecyclerView 的目的。

You should not use hashCode() as an ID as it is not guaranteed to be unique.您不应该使用hashCode()作为 ID,因为它不能保证是唯一的。 My guess is that many of your items are returning the same hash.我的猜测是您的许多项目都返回相同的哈希值。 Please try implementing a unique ID for each item and use the it in your getItemId() method.请尝试为每个项目实现一个唯一 ID,并在您的getItemId()方法中使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM