android RecyclerView數(shù)據(jù)更新后視圖不刷新:問題詳解及解決方案
在Android開發(fā)中,RecyclerView是常用的數(shù)據(jù)展示組件。然而,更新數(shù)據(jù)后視圖卻無法刷新,是開發(fā)者常遇到的問題。本文將分析此問題,并提供解決方案。
問題描述:
開發(fā)者使用RecyclerView展示用戶數(shù)據(jù),網(wǎng)絡(luò)請求(異步操作)完成后,數(shù)據(jù)更新但視圖未刷新。數(shù)據(jù)更新在適配器中進(jìn)行,網(wǎng)絡(luò)請求使用異步回調(diào)(非主線程)。
代碼示例:
初始化RecyclerView:
userRecyclerViewAdapter adapter = new userRecyclerViewAdapter(this.fragment.getActivity()); this.binding.users.setAdapter(adapter); this.binding.users.setLayoutManager(new LinearLayoutManager(this.fragment.getContext()));
更新數(shù)據(jù):
public void getData(boolean append) { // ... 省略部分代碼 userApi api = new userApi(activity); api.index(dto) .thenAccept((response) -> { List<IndexUserApiResponseDto.User> data = res.getContent(); userRecyclerViewAdapter adapter = (userRecyclerViewAdapter) this.binding.users.getAdapter(); List<userRecyclerViewAdapter.Item> items = new ArrayList<>(); data.stream().forEach(user -> { IndexUserApiResponseDto.User.UserArchive userArchive = user.getUserArchive(); if (userArchive != null) { userRecyclerViewAdapter.Item item = new userRecyclerViewAdapter.Item(); item.setCover(userArchive.getCover()); // ... 設(shè)置item的其他屬性 items.add(item); } }); // 更新ui必須在主線程 activity.runOnUiThread(() -> { if (!items.isEmpty()) { if (append) { adapter.addAll(items); } else { adapter.resetAll(items); } adapter.notifyDataSetChanged(); } }); }) .exceptionally(LogUtils::throwException) .thenRun(() -> { // ... 省略部分代碼 }); }
適配器代碼:
public class userRecyclerViewAdapter extends RecyclerView.Adapter<UserViewHolder> { private final Activity activity; private final List<Item> items = new ArrayList<>(); // ... 省略部分代碼 public void addAll(List<Item> items) { this.items.addAll(items); } public void resetAll(List<Item> items) { this.items.clear(); this.items.addAll(items); } @Override public void onBindViewHolder(@NonNull UserViewHolder holder, int position) { Item item = this.items.get(position); holder.getTitleView().setText(item.getTitle()); //確保所有屬性都已設(shè)置 // ... } @Override public int getItemCount() { return this.items.size(); } }
問題分析及解決方案:
-
異步操作與UI更新: 網(wǎng)絡(luò)請求在后臺(tái)線程執(zhí)行,數(shù)據(jù)更新也發(fā)生在后臺(tái)線程。直接操作UI會(huì)拋出異常。解決方案:使用runOnUiThread()將數(shù)據(jù)更新和notifyDataSetChanged()放在主線程執(zhí)行。
-
notifyDataSetChanged()的調(diào)用: 雖然代碼調(diào)用了addAll()和resetAll(),但RecyclerView并不知道數(shù)據(jù)已改變,需要顯式調(diào)用notifyDataSetChanged()通知RecyclerView刷新。
-
數(shù)據(jù)完整性: 確保Item對象的屬性都已正確賦值。
-
空數(shù)據(jù)處理: 檢查items列表是否為空??樟斜碚{(diào)用notifyDataSetChanged()也不會(huì)刷新視圖。
通過在thenAccept塊中使用runOnUiThread包裹數(shù)據(jù)更新和notifyDataSetChanged(),并確保Item對象數(shù)據(jù)完整以及處理空數(shù)據(jù)情況,即可解決RecyclerView數(shù)據(jù)更新后視圖不刷新的問題。 代碼示例中已體現(xiàn)了這些改進(jìn)。