【问题标题】:Android RecyclerView items shuffles on scrollAndroid RecyclerView 项目在滚动时随机播放
【发布时间】: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);
  1. 增加了 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。

标签: java android android-recyclerview


【解决方案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) - 我做不到。
      猜你喜欢
      • 1970-01-01
      • 2022-08-14
      • 2018-07-14
      • 1970-01-01
      • 2021-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-23
      相关资源
      最近更新 更多