如何解决SwipeRefreshLayout刷新RecyclerView时API新数据追加到末尾的问题
问题根因
下拉刷新时新数据追加在旧数据末尾的核心原因是:每次拉取新数据前没有清空存储旧数据的全局列表,新数据直接追加到了原有列表末尾,同时每次接口请求成功后重复初始化RecyclerView相关实例也属于不必要的冗余操作,会带来额外性能损耗。
修改方案
步骤1:将RecyclerView的初始化逻辑移动到onCreate方法中,全局只执行一次
步骤2:每次接口返回新数据前先清空原有数据,添加新数据后通知适配器刷新列表
步骤3:修正SwipeRefreshLayout的刷新状态控制逻辑,请求完成后再关闭刷新动画
完整修改后的代码片段如下:
首先修改onCreate方法:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_state_report); View mainLayout = findViewById(R.id.mainLayout); Drawable drawable = mainLayout.getBackground(); drawable.setAlpha(20); refreshLayout = findViewById(R.id.mainLayout); // 初始化RecyclerView 全局仅执行一次 recyclerView = findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new LinearLayoutManager(this)); itemArrayList = new ArrayList<>(); adapter = new CustomAdapter(this, itemArrayList); recyclerView.setAdapter(adapter); refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { // 不要立刻关闭刷新状态,等待接口请求完成后再关闭 loadStateReport(); } }); loadStateReport(); }
修改loadStateReport方法:
public void loadStateReport () { Log.d ("debugging", "entered the loadSateReport() Fn."); RequestQueue requestQueue = Volley.newRequestQueue(StateReportActivity.this); JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, REPORT_URL, null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { try { // 先清空旧数据 itemArrayList.clear(); JSONArray array = response.getJSONArray("regionData"); for (int i = 0; i < array.length(); i++) { JSONObject object = array.getJSONObject(i); String region = object.getString("region"); Long activeCases = object.getLong("activeCases"); Long newInfected = object.getLong("newInfected"); Long recovered = object.getLong("recovered"); Long newRecovered = object.getLong("newRecovered"); Long deceased = object.getLong("deceased"); Long newDeceased = object.getLong("newDeceased"); Long total = object.getLong("totalInfected"); itemArrayList.add(new Item(region, activeCases, newInfected, recovered, newRecovered, deceased, newDeceased, total)); } // 通知适配器数据已变更,刷新列表 adapter.notifyDataSetChanged(); // 关闭刷新状态 refreshLayout.setRefreshing(false); } catch (JSONException e) { e.printStackTrace(); refreshLayout.setRefreshing(false); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Toast.makeText(StateReportActivity.this, "网络请求失败,请检查网络设置", Toast.LENGTH_SHORT).show(); // 接口请求失败也要关闭刷新状态 refreshLayout.setRefreshing(false); } }); requestQueue.add(jsonObjectRequest); Log.d("debugging", "ObjectRequest added to the queue."); }
改动说明
- RecyclerView的初始化逻辑挪到onCreate中仅执行一次,避免重复创建实例带来的性能损耗
- 每次接口返回数据前先调用
itemArrayList.clear()清空原有旧数据,再添加新拉取的数据,就不会出现数据追加的问题 - 修正了SwipeRefreshLayout的状态控制逻辑,只有在接口请求完成(无论成功失败)才关闭刷新动画,交互体验更符合预期。
内容的提问来源于stack exchange,提问作者Dilip
相关产品推荐
相关产品推荐

