Android RecyclerView刪除多個選中的item 及 局部刷新
最近看了一個慕課網上的實戰課, Android通用框架設計與完整電商APP開發
,這個課也是2/3年之前的視頻了,所以購物車功能的有些地方不太對了,我就優化了一下,主要是兩個方面:
- 刪除多個選中的item
- 局部刷新
關於所有item的選中狀態爲選中時,recyclerview外部的全選按鈕狀態的更新,加一個回調就可以實現,具體源碼可以去我的 碼雲 參考,主要是ShopCartAdapter
和 ShopCartDelegate
兩個類,都在com.wll.ec.fast.main.cart
包下。
這裏的使用了BaseRecyclerViewAdapterHelper,不太瞭解的同學可以先去github 上 瞭解一下。
刪除多個選中的item
首先是刪除多個選中的商品後數據顯示錯誤問題,而且總價是顯示所有未選中和選中商品的總價,刪除商品後總價並沒有改變,我對此處進行了優化,總價是隨着商品選中狀態的改變而改變的,且若刪除選中的商品總價也會改變,效果圖對比如下:
可以看到最後兩個怎麼點擊也刪除不了。而且,總價變化也不對。
來看一下改進之後的效果,如下:
刪除選中item的思路如下:首先要記錄是哪些位置的item被選中了,將選中的對應位置數據從adapter的數據中刪除,並調用
notifyItemRemoved(int position)
notifyItemRangeRemoved(int positionStart, int itemCount)
注意,如果不調用上面兩個方法,而是隻刪除數據並更新數據,最後再notifyItemRangeRemoved的話會導致數據錯亂,下面附效果圖:
最後我們要把數據中position位置後面的數據中記錄該條數據位置信息的數據更新。如果不這麼做的話,會導致後續刪除position 位置的數據時,刪除的是其他位置的數據,如下圖:
所以一定要記得更新數據。
相關代碼如下:
@OnClick(R2.id.tv_top_shop_cart_remove_selected)
void onClickRemoveSelectedItem() {
double subPrice = 0;
final List<MultipleItemEntity> data = mAdapter.getData();
//要刪除的數據
final List<MultipleItemEntity> deleteEntities = new ArrayList<>();
for (MultipleItemEntity entity : data) {
final boolean isSelected = entity.getField(ShopCartItemFields.IS_SELECTED);
if (isSelected) {
deleteEntities.add(entity);
subPrice = subPrice + ((double) entity.getField(ShopCartItemFields.PRICE)) *
(int) entity.getField(ShopCartItemFields.COUNT);
}
}
int size = deleteEntities.size();
int entityPosition = 0;
for (int i = size - 1; i >= 0; i--) {
entityPosition = deleteEntities.get(i).getField(ShopCartItemFields.POSITION);
if (entityPosition < mAdapter.getItemCount()) {
// mAdapter.getData().remove(entityPosition);
mAdapter.remove(entityPosition);
}
}
mAdapter.updateItemRangeFieldPosition(entityPosition);
// mAdapter.notifyItemRangeRemoved(entityPosition, mAdapter.getItemCount() - entityPosition);
updateTotalPrice(subPrice);
checkItemCount();
}
注意,此處remove的時候是for循環是從後面size-1先開始的,如果從前面開始,仔細想一下,刪除第一個,要notifyItemRangeRemoved 第一個後面所有的,然後下面還要繼續循環,如果我們從後面開始,那麼隨着item數量的減少,需要notifyItemRangeRemoved數量就減少。
局部刷新
下面附三種方法對比圖:
notifyDataSetChanged():
notifyItemRangeChanged(int positionStart, int itemCount):
notifyItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload):
相關代碼如下:
@OnClick(R2.id.icon_shop_cart_select_all)
void onClickSelectAll() {
boolean isSelectedAll = mAdapter.getIsSelectedAll();
if (isSelectedAll){
mIconSelectAll.setTextColor(Color.GRAY);
} else {
mIconSelectAll.setTextColor(ContextCompat.getColor(getContext(), R.color.app_main));
}
mAdapter.setIsSelectedAll(!isSelectedAll);
// mAdapter.notifyDataSetChanged();
// mAdapter.notifyItemRangeChanged(0, mAdapter.getItemCount());
mAdapter.notifyItemRangeChanged(0, mAdapter.getItemCount(), "checkBtn");
mAdapter.updateAllSelected(!isSelectedAll);
}