Android RecyclerView 项目在滚动时随机播放

Posted

技术标签:

【中文标题】Android RecyclerView 项目在滚动时随机播放【英文标题】:Android RecyclerView items shuffles on scroll 【发布时间】:2020-09-25 11:33:59 【问题描述】:

我的多视图类型 RecyclerView 适配器的项目/单元格在滚动上随机播放。我浏览了以下所有可能的解决方案,但没有一个有效。

1.

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


setHasStableIds(true);
    增加了 RecyclerView 的缓存

如果有人有任何解决方案,请分享。

我的适配器类

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

【问题讨论】:

能否请您显示您的适配器的代码以及它如何在回收站视图中使用?你使用 StaggeredGridLayoutManager 吗? 能否请您在此处发布您的适配器文件,以便我检查您做错了什么? @Rahul 已更新,请立即查看。 @AkhileshMani 我已经发布了答案,如果您有任何不明白的地方请检查并告诉我。 @ZSergei 我使用了 LinearLayoutManager... 我刚刚在 RV 中做了 setAdapter。 【参考方案1】:

我研究过这种类型的RecyclerView,这是与多个view-type 一起使用的DynamicAdapter 类。我希望您对如何使用它有所了解。

    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) 

    

如果您有任何疑问,请告诉我,Happy Coding :)

【讨论】:

【参考方案2】:

使 RecyclerView ViewModel 不可回收。我认为 recyclerview 默认设置为刷新,因此,洗牌项目 例如

class YourViewModel extends RecyclerView.ViewHolder 

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

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

     

此外,您可以在填充项目之前使用 Collection.sort(items) 实现排序方法,因此即使视图被回收,项目仍然保持排序(例如按 id)。

【讨论】:

setIsRecyclable(false) - 我做不到。【参考方案3】:

您不应该使用hashCode() 作为ID,因为它不能保证是唯一的! 我的猜测是您的许多项目都返回相同的哈希值。 请尝试为每个项目实现一个唯一 ID,并在您的 getItemId() 方法中使用它。

【讨论】:

【参考方案4】:

你可以试试:

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

也覆盖:

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

为recyclerview增加缓存的一种方法是:

recyclerView.setItemViewCacheSize(20)

您还可以借助 LinearLayoutManager 的方法calculateExtraLayoutSpace 获得额外的空间。我已添加到文档的链接。

您也可以使用:

setIsRecyclable(false);

但这超出了使用 RecyclerView 的目的。

【讨论】:

setIsRecyclable(false) - 我做不到。

以上是关于Android RecyclerView 项目在滚动时随机播放的主要内容,如果未能解决你的问题,请参考以下文章

Android - 网格中项目之间的 RecyclerView 间距

在recyclerview项目android中更改视图之间的焦点

Android RecyclerView 选择第一个项目

Android Recyclerview项目Textview在某些项目中不会显示

Android-检查多个项目并从 RecyclerView 列表中删除

Android:RecyclerView里面的RecyclerView,滚动到底部