首先,我的 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);
在您的适配器类中重写此方法并将位置替换为 getItemViewType(position)
@Override
public int getItemViewType(int position) {
return position;
}
在
public void onBindViewHolder()
添加
holder.setIsRecyclable(false);
上述方法对我来说在所有情况下都不起作用,我不想牺牲可回收性。我发现的唯一可行的解决方案是将适配器内这些方法的both的返回修改为“position”值:
override fun getItemViewType(position: Int): Int {
return position
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
返回的位置将始终正确。如果使用viewType则需要修改。
就我而言,发生此问题是因为我在一个
setHasStableIds(true)
中有 RecyclerView.Adapter
(事实上,自从我在 Xamarin.Android 中工作以来,它就是 HasStableIds = true;
)。
删除该行后(
HasStableIds
默认为false
),所有位置都恢复正常,我不需要禁用回收或从position
返回GetItemViewType(int position)
(这很好,因为我实际上使用此方法可以在多个 ViewHolder
类型之间进行选择)。然后出于兴趣,我尝试启用 HasStableIds
并覆盖 long GetItemId(int position)
– 它也运行良好。
所以我的结论是:如果由于某种原因你需要启用
HasStableIds
,你应该在 long GetItemId(int position)
的子类中重写 both
int GetItemViewType(int position)
和 RecyclerView.Adapter
。如果您没有唯一的项目 ID 和/或不同的视图类型,只需返回 position
参数即可完成工作。
令人难以置信的是,这里有多少答案只是停用了回收器适配器的整个目的,而没有人真正正确地解决了它。
您将通过以下方式彻底毁坏回收适配器:
将 setIsRecyclable 设置为 false。它停用回收。从而带来高绩效支出。
将 setHasStableIds 设置为 false。回收器适配器具有内部动态 ID,以便正确回收。是的,这会解决您的问题,但它又会降低性能。
是的,我不知道如何正确解决这个问题(我猜它只是使用 ViewHolder 对象并尽可能少地使用确切的位置,但我还无法理解这个问题)但我所有的在每个 Stackoverflow 帖子中看到的都是相同的解决方案,强烈建议不要在 Google 和在这里试图为人们提供建议的 Google 员工的多次演讲中执行这些解决方案。