【问题标题】:RecyclerView wrong position set onBindViewHolderRecyclerView设置onBindViewHolder位置错误
【发布时间】:2020-10-08 09:36:19
【问题描述】:

起初,我的 RecyclerView 项目还可以,但在滚动时,项目显示在错误的位置,例如:项目 6 显示在位置 67。虽然 onClick 侦听器和 getAdapterPosition() 效果很好并显示正确的项目。为什么?

import android.content.Context;
import android.graphics.Typeface;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.neganet.darotabii.R;
import com.neganet.darotabii.beans.headers_Bean;
import java.util.List;
public class FSecAdapter2 extends RecyclerView.Adapter<FSecAdapter2.mViewHolder> {

    private static List<headers_Bean> items_t;
    private static int secNo;
    private Typeface font;
    private boolean showSoreName;
    private static Context mContext;
    private static String сolorString;

  private static String fSubjectText="";
    private static Static_Datas static_datas;
    private static QDataGetter dataGetter;

public FSecAdapter2(List<headers_Bean> t_items, Context cnt, int secNo) {
            setHasStableIds(true);

            this.mContext=cnt;
            this.items_t = t_items;
            this.static_datas=new Static_Datas(mContext);
            this.secNo=secNo;
         }

        public static class mViewHolder extends RecyclerView.ViewHolder  implements View.OnClickListener {
            private OnTitleClickListener titClickListener;

            static TextView title;
            public mViewHolder(View itemView) {
                super(itemView);
                    this.title = (TextView) itemView.findViewById(R.id.title2);
                    this.title.setTypeface(static_datas.get_titr_1_Font());
                    this.title.setOnClickListener(this);
                    this.titClickListener=(OnTitleClickListener) FSecAdapter2.mContext;
            }
            @Override
            public void onClick(View v) {
                    titClickListener.onTitleClick(v,items_t.get(getAdapterPosition()).serial+"*"+items_t.get(getAdapterPosition()).titr);
            }

        }

        @Override
        public mViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View itemView;
            itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.titles_item, parent, false);
            mViewHolder mVH=new mViewHolder(itemView);
            return mVH;
        }

        @Override
        public void onBindViewHolder(mViewHolder holder, int position) {
            final headers_Bean curHbean=this.items_t.get(position);
            try {

                holder.title.setText(static_datas.fa_Ye_Ke(curHbean.titr));
           } catch (Exception e) {
                e.printStackTrace();
            }

        }

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



        public interface OnTitleClickListener {
            public void onTitleClick(View v, String serial);
        }

     public void updateData(headers_Bean newHead){
         items_t.add(items_t.size(),newHead);
         notifyItemInserted(items_t.size()-1);
     }}

在片段中:

        mAdapter = new FSecAdapter2(titList,getActivity(),secNo);
    final LinearLayoutManager mLayoutManager = new LinearLayoutManager(this.getActivity());
    mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    titRecycle.setLayoutManager(mLayoutManager);
    titRecycle.setItemAnimator(new DefaultItemAnimator());
    titRecycle.setAdapter(mAdapter);

【问题讨论】:

  • public void onBindViewHolder() 添加holder.setIsRecyclable(false);
  • @kashyap jimuliya - 非常感谢。有用。但是还有另一种方法可以使用 RecyclerView 的回收
  • 你是否在其他Activity中实现interface OnTitleClickListener()
  • 是的。在 MainActivity
  • 我不确定这是否会有所帮助,但就我而言,它确实有效! stackoverflow.com/a/30301563/4035628

标签: android android-recyclerview


【解决方案1】:

public void onBindViewHolder()

添加

holder.setIsRecyclable(false);

【讨论】:

  • 以这种方式滚动的项目更改为其初始值。
  • @sasan,检查您的notify() 方法一次或分享您的代码以更好地理解它。
  • 但是当项目更多时,这会使 recyclerview 滞后
  • @SunnyBhadana 您可以删除此行并通过为每种类型的视图创建视图持有者来实现更好的适配器模式。这将使 recyclerView 可回收且平滑。
  • 如果您不将视图设置为自行回收,那么 RecyclerView 的用途是什么?
【解决方案2】:

在您的适配器类中重写此方法并将位置替换为 getItemViewType(position)

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

【讨论】:

  • 究竟缺少什么!.. 谢谢
  • 像个老板!谢谢。
  • 这应该是正确的答案,因为我们确实需要使用可回收功能
  • 为什么会修复它?
  • 完美,谢谢!
【解决方案3】:

上述方法都不适用于我,我不想牺牲可回收性。我发现的唯一可行的解​​决方案是将适配器内 both 的返回值修改为“position”值:

override fun getItemViewType(position: Int): Int {
        return position
}

override fun getItemId(position: Int): Long {
       return position.toLong()
}

返回的位置总是正确的。如果您使用的是 viewType,则需要对其进行修改。

【讨论】:

    【解决方案4】:

    在我的情况下,这个问题正在发生,因为我在一个 RecyclerView.Adapter 中有 setHasStableIds(true)(事实上,因为我在 Xamarin.Android 中工作,它是 HasStableIds = true;)。

    删除该行后(HasStableIds 默认为false),所有位置都恢复正常,我不需要禁用回收或从GetItemViewType(int position) 返回position(这很好,因为我实际上使用这种方法在多个ViewHolder类型之间进行选择)。然后出于兴趣,我尝试启用HasStableIds 并覆盖long GetItemId(int position) - 它也运行良好。

    所以我的结论是:如果出于某种原因您需要启用HasStableIds,您应该在RecyclerView.Adapter 的子类中覆盖 long GetItemId(int position)int GetItemViewType(int position)。如果您没有唯一的项目 ID 和/或不同的视图类型,只需返回 position 参数即可。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-08
      • 1970-01-01
      • 2013-04-21
      • 2018-02-12
      • 1970-01-01
      相关资源
      最近更新 更多