SwipeRefreshLayout下拉刷新返回重复数据问题求助
SwipeRefreshLayout下拉刷新数据重复问题解决
问题根源
- 全局集合
moviesList每次刷新时未清空,直接调用addAll追加新数据,导致旧数据残留重复。 - 下拉刷新时重复调用
initViews(),该方法会重复初始化布局管理器、创建新Adapter,还会重复发起数据请求并注册观察者,多次触发数据添加逻辑。 - 每次数据返回后都重新创建Adapter并设置给RecyclerView,不仅没必要,还可能引发额外问题。
解决方案
1. 拆分初始化逻辑,分离一次性操作和刷新操作
将RecyclerView布局管理器、Adapter初始化这些只需要执行一次的代码单独抽离,避免刷新时重复执行。
2. 刷新前清空数据集合
发起新请求前先清空moviesList,确保新数据是从头添加,不会和旧数据叠加。
3. 复用Adapter,避免重复创建
初始化时创建一次Adapter并绑定到RecyclerView,后续仅需更新数据集合后通知Adapter刷新即可。
4. 优化数据请求与观察者逻辑
确保数据请求和观察者注册只执行必要的次数,避免重复监听导致多次添加数据。
修改后的完整代码
public class HomeActivity extends AppCompatActivity { private RecyclerView recyclerView; private ProgressDialog pd; private SwipeRefreshLayout swipeRefreshLayout; private List<MovieModel> moviesList; private HomeMovieAdapter adapter; private MovieListViewModel movieListViewModel; private FavouriteDbHelper favouriteDbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); recyclerView = findViewById(R.id.recyclerview_home); swipeRefreshLayout = findViewById(R.id.main_content_home); Toolbar toolbar = findViewById(R.id.toolBar_home); favouriteDbHelper = new FavouriteDbHelper(this); moviesList = new ArrayList<>(); movieListViewModel = new ViewModelProvider(this).get(MovieListViewModel.class); setSupportActionBar(toolbar); // 仅初始化一次RecyclerView相关配置 initRecyclerView(); // 设置下拉刷新监听 setupSwipeRefresh(); // 首次加载数据 loadPopularMovies(); } // 初始化RecyclerView,只执行一次 private void initRecyclerView(){ pd = new ProgressDialog(this); pd.setMessage("Fetching Movies..."); pd.setCancelable(false); pd.show(); adapter = new HomeMovieAdapter(this,moviesList); // 根据屏幕方向设置列数 int spanCount = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT ? 2 : 4; recyclerView.setLayoutManager(new GridLayoutManager(this, spanCount)); recyclerView.setItemAnimator(new DefaultItemAnimator()); recyclerView.setAdapter(adapter); } // 配置下拉刷新逻辑 private void setupSwipeRefresh(){ swipeRefreshLayout.setColorSchemeResources(android.R.color.holo_orange_dark); swipeRefreshLayout.setOnRefreshListener(() -> { loadPopularMovies(); Toast.makeText(HomeActivity.this, "Movies Refreshed", Toast.LENGTH_SHORT).show(); }); } // 加载电影数据的核心逻辑 private void loadPopularMovies(){ // 清空旧数据,避免重复 moviesList.clear(); // 请求第一页数据 movieListViewModel.searchMoviesPage(1); movieListViewModel.getPopularMovies().observe(this, movieModels -> { try { if (movieModels != null){ moviesList.addAll(movieModels); // 通知Adapter数据更新 adapter.notifyDataSetChanged(); recyclerView.smoothScrollToPosition(0); } // 关闭刷新状态 if (swipeRefreshLayout.isRefreshing()){ swipeRefreshLayout.setRefreshing(false); } pd.dismiss(); }catch (Exception e){ e.printStackTrace(); // 异常时也要关闭加载状态 if (swipeRefreshLayout.isRefreshing()){ swipeRefreshLayout.setRefreshing(false); } pd.dismiss(); } }); } }
关键优化点说明
- 把初始化RecyclerView的逻辑抽离到
initRecyclerView(),仅在Activity创建时执行一次,避免重复创建布局管理器和Adapter。 - 每次刷新调用
loadPopularMovies()时,先执行moviesList.clear()清空旧数据,从根源解决重复问题。 - 复用同一个Adapter,数据更新后调用
adapter.notifyDataSetChanged(),既保证界面刷新,又提升性能。 - 下拉刷新仅触发数据重新加载,不再执行冗余的初始化操作,逻辑更简洁清晰。
内容的提问来源于stack exchange,提问作者Ukeme Elijah
相关产品推荐
相关产品推荐

