RecyclerView向下滚动后Intent传递数据丢失问题求助
问题原因
你的代码核心错误是变量作用域和RecyclerView复用逻辑冲突,具体有几个典型问题:
- 收藏列表初始化位置错误:
favoritos收藏列表放在ViewHolder构造函数中初始化,每次滚动创建新的ViewHolder时都会清空之前的收藏记录,导致滚动后数据丢失。 - 控件声明为全局/静态变量:
lc、fit按钮、itemAtual、favoriteButton都被声明为全局甚至静态变量,每次onBindViewHolder绑定新item时都会覆盖这些变量的引用,导致操作的永远是最后一个可见item的控件和数据。 - 直接跨组件修改其他Activity的Intent:在Adapter中直接修改
VeganoActivity.intentLanches2不符合组件职责分离,也容易出现数据同步问题。
修复方案
按以下步骤修改代码即可解决问题:
1. 调整变量作用域
删除Adapter中错误的全局/静态变量声明,将item独有控件放到ViewHolder内部,收藏列表放到Adapter全局初始化:
public class AdapterLanches extends RecyclerView.Adapter<AdapterLanches.MyViewHolder> implements Filterable { private List<Lanches> listaLanches; private List<Lanches> listaLanchesCompleta; ArrayList<CharSequence> favoritos; // 收藏列表全局唯一 boolean fav = false; int estadoPrograma; // 定义回调接口,把收藏数据传给宿主Activity public interface OnFavoritosChangeListener { void onFavoritosChanged(ArrayList<CharSequence> favoritos); } private OnFavoritosChangeListener listener; // 构造函数传入回调 public AdapterLanches(List<Lanches> listaLanches, OnFavoritosChangeListener listener) { this.listaLanches = listaLanches; listaLanchesCompleta = new ArrayList<>(this.listaLanches); favoritos = new ArrayList<>(); // 收藏列表只在Adapter创建时初始化一次 this.listener = listener; } public class MyViewHolder extends RecyclerView.ViewHolder { public MaterialFavoriteButton favoriteButton; TextView titulo; Button lc,fit; // item控件放到ViewHolder内部 public MyViewHolder(@NonNull View itemView) { super(itemView); lc = itemView.findViewById(R.id.lc); fit = itemView.findViewById(R.id.fit); favoriteButton = itemView.findViewById(R.id.favorite); titulo = itemView.findViewById(R.id.textnomeLanchesId); favoriteButton.setOnFavoriteChangeListener(new MaterialFavoriteButton.OnFavoriteChangeListener() { @Override public void onFavoriteChanged(MaterialFavoriteButton buttonView, boolean favorite) { int posicao = getAdapterPosition(); if (posicao == RecyclerView.NO_POSITION) return; // 防止位置无效崩溃 Lanches item = listaLanches.get(posicao); if (favorite) { if (!favoritos.contains(item.getTitulo())) { favoritos.add(item.getTitulo()); } } else { favoritos.remove(item.getTitulo()); } // 通过回调把最新收藏列表传给Activity处理Intent listener.onFavoritosChanged(favoritos); } }); } }
2. 调整onBindViewHolder逻辑,操作holder内部的控件
@Override public void onBindViewHolder(@NonNull final MyViewHolder holder, final int position) { Lanches itemAtual = listaLanches.get(position); // 局部变量,不会被覆盖 holder.titulo.setText(itemAtual.getTitulo()); // 操作当前holder的控件,不要用全局变量 if (itemAtual.getId() == 0){ holder.fit.setVisibility(View.GONE); holder.lc.setVisibility(View.GONE); } else if (itemAtual.getId() == 1){ holder.lc.setVisibility(View.VISIBLE); holder.fit.setVisibility(View.GONE); } else if (itemAtual.getId() == 2){ holder.fit.setVisibility(View.VISIBLE); holder.lc.setVisibility(View.GONE); } // 同步收藏按钮状态,防止复用后状态错乱 holder.favoriteButton.setFavorite(favoritos.contains(itemAtual.getTitulo()), false); }
3. 宿主Activity处理Intent逻辑
在创建Adapter的Activity中实现回调接口,更新Intent:
// 初始化Adapter时传入回调 AdapterLanches adapter = new AdapterLanches(lista, new AdapterLanches.OnFavoritosChangeListener() { @Override public void onFavoritosChanged(ArrayList<CharSequence> favoritos) { intentLanches2.putExtra("titulo", favoritos); } });
内容的提问来源于stack exchange,提问作者Matheus Soléo
相关产品推荐
相关产品推荐

