RecyclerView wrong position set onBindViewHolder

允我心安 提交于 2021-01-21 06:16:37

问题


At First, my RecyclerView items are ok, but on scrolling, items are shown on the wrong position for example: item 6 shown in position 67. Although onClick listener and getAdapterPosition() works good and shows correct items. WHY?

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

and in fragment:

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

回答1:


in public void onBindViewHolder()

add

holder.setIsRecyclable(false);



回答2:


In your adapter class override this method and replace position to getItemViewType(position)

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



回答3:


None of the methods above worked in every situation for me and I don't want to sacrifice the recyclability. The only working solution that I found is to modify the return for both of these methods inside the adapter to "position" values:

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

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

The returned position will be always correct. It needs to be modified if you are using viewType.




回答4:


In my case this problem was happening because I had setHasStableIds(true) in one RecyclerView.Adapter (in fact, it was HasStableIds = true; since I work in Xamarin.Android).

After removing that line (HasStableIds is false by default), all positions got back to normal and I didn't need to disable recycling or to return position from GetItemViewType(int position) (which is nice because I actually use this method to choose between multiple ViewHolder types). Then just out of interest I tried to enable HasStableIds and override long GetItemId(int position) – it also worked well.

So my conclusion is: if for some reason you need to enable HasStableIds, you should override both long GetItemId(int position) and int GetItemViewType(int position) in your RecyclerView.Adapter's subclass. If you do not have unique item IDs and/or different view types, just returning back the position parameter will do the job.



来源:https://stackoverflow.com/questions/38182223/recyclerview-wrong-position-set-onbindviewholder

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