问题
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