大家好,我們又見面了,很高興證明我又有東西跟大家分享了上星期我寫了一篇關(guān)于[Android:玩轉(zhuǎn)購物車界面和邏輯只需要一層Recyclerview,一個(gè)二層for循環(huán)和三個(gè)屬性](http://www.lxweimin.com/p/6c3328f87fc9),反響比我想象中好很多,而且有幸被DiyCode轉(zhuǎn)發(fā)了,我自己本人也沒去投稿也是有一個(gè)朋友告訴我才知道這件事~不管怎么一個(gè)陰差陽錯(cuò),這也證明最近一段時(shí)間沒有白做項(xiàng)目。
連上實(shí)習(xí)出社會(huì)工作一年多了,相比于其他辦公室政治的職業(yè),真心覺得程序猿是比較和諧的,無論是誰只要是程序猿坐在一起都可以聊大半天,互相去分享經(jīng)驗(yàn)和學(xué)習(xí)。當(dāng)然這次來不是為了跟人炫耀什么,只是想來再次分享一些更勁爆的項(xiàng)目經(jīng)驗(yàn),也是關(guān)于商城的,不過這次是購物車之后的訂單列表。我們先看看界面需求:
那接下來就分析一下我自己的理解和做法。
如果不想聽我啰嗦的人可以直接去下載源碼源碼下載鏈接
這樣看上去,我們就看到有三個(gè)不同的item。
1.一張大訂單的含有所有信息的item:
2.一張大訂單里面分為一張張小訂單,每張小訂單就代表一間店鋪的所有商品,而且每間商鋪的第一個(gè)商品需要帶小訂單編號(hào)和商鋪名字的header:
3.下面的就是小訂單內(nèi)非第一件商品的item(不含header):
看完這個(gè)界面需求,相信很多人都跟我一樣,覺得用兩層嵌套的RecyclerView、隱藏和顯示商品的頭布局不就可以完成這樣的界面了?
確實(shí)做界面的時(shí)候我是這樣做的,但是當(dāng)把數(shù)據(jù)插入的時(shí)候,嵌套View的問題就無緣無故出現(xiàn)了:
可能gif圖大家還看不出問題。
明明是一張大訂單里面有兩張不同商鋪的小訂單,總共有五件商品,兩張小訂單號(hào)分別尾數(shù)是133和601,但當(dāng)我們上拉RecyclerView然后再下拉回去的時(shí)候,我發(fā)現(xiàn):
本來同屬于一張大訂單的尾數(shù)為133和601的兩張小訂單本來5件商品卻無緣無故消失了剩下一件商品~
得到這種結(jié)果令我非常詫異,無論我用什么樣的方式去驗(yàn)證這樣的嵌套R(shí)ecyclerView的做法,都是會(huì)出現(xiàn)這樣的情況。我的一位從我學(xué)習(xí)Android以來一直幫助我的師兄,他也去檢查過我寫的xml布局和adapter,也沒發(fā)現(xiàn)問題,但顯示的時(shí)候總會(huì)出現(xiàn)布局丟失的情況。
最后我發(fā)現(xiàn)這是一條死胡同,一個(gè)我無法解釋的bug。
<u>其實(shí)在用RecyclerView嵌套的時(shí)候我已經(jīng)發(fā)現(xiàn)很多無緣無故的顯示bug,所以我勸大家還是少用布局嵌套,不然就像我這樣作死~
</u>
既然這樣走嵌套R(shí)ecyclerView是一條死胡同,那只能用不嵌套的做法來做了,下面我就講講我的師兄,他給我的一個(gè)做法。確實(shí)在這里的做法和邏輯都是師兄寫的,我只是做了實(shí)現(xiàn)和筆錄~
看這種做法之前,我們先看看后臺(tái)返回來的數(shù)據(jù)是怎么樣的,才好思考往下怎么去做:
我把以上三張圖的數(shù)據(jù)結(jié)構(gòu)簡化一下:
"result":{
"大訂單List":[
大訂單1{...},
大訂單2 {
大訂單的相關(guān)信息
"商品List":[
"商品1"{
"商品信息"
"商鋪信息":{
商品所在商鋪的信息, 即小訂單信息
}
},
"商品2"{...},
"商品3"{...},
]
},
大訂單3{...}
]
}
看上去,三層數(shù)據(jù)怎么把他用一層RecyclerView顯示出來呢?這里,不得不說師兄想的方法非常有意思。
他把這里的所有數(shù)據(jù)分成三種數(shù)據(jù)類型,并把RecyclerView分成三種不同的布局,對(duì)返回來的數(shù)據(jù)用不同的對(duì)象進(jìn)行排序并且把排好序的數(shù)據(jù)最后放進(jìn)一條List<Object>,讓adapter去判斷該顯示哪種布局:
(1)GoodsOrderInfo 表示每個(gè)小訂單的頭部信息(訂單號(hào)、訂單狀態(tài)、店鋪名稱)
(2)OrderGoodsItem 表示小訂單中的商品
(3)OrderPayInfo 表示大訂單的支付信息(金額、訂單狀態(tài))
我們來看看代碼:
public class OrderDataHelper {
/**
* List<Object>有三種數(shù)據(jù)類型:
* 1、GoodsOrderInfo 表示每個(gè)小訂單的頭部信息(訂單號(hào)、訂單狀態(tài)、店鋪名稱)
* 2、OrderGoodsItem 表示小訂單中的商品
* 3、OrderPayInfo 表示大訂單的支付信息(金額、訂單狀態(tài))
* @param resultList
* @return
*/
public static List<Object> getDataAfterHandle(List<OrderSummary> resultList) {
List<Object> dataList = new ArrayList<Object>();
//遍歷每一張大訂單
for (OrderSummary orderSummary : resultList) {
//大訂單支付的金額和訂單狀態(tài)
OrderPayInfo orderPayInfo = new OrderPayInfo();
orderPayInfo.setTotalAmount(orderSummary.getTotalPrice());
orderPayInfo.setStatus(orderSummary.getStatus());
orderPayInfo.setId(orderSummary.getId());
//小訂單商品
List<OrderGoodsItem> orderDetailList = orderSummary.getOrderDetailList();
Map<String, List<OrderGoodsItem>> orderGoodsMap = new HashMap<String, List<OrderGoodsItem>>();
Map<String, GoodsOrderInfo> orderInfoMap = new HashMap<String, GoodsOrderInfo>();
//遍歷每個(gè)大訂單里面的商品
for (OrderGoodsItem orderGoodsItem : orderDetailList) {
//獲取商品里面的商鋪信息的訂單號(hào)
String orderCode = orderGoodsItem.getOrder().getOrderCode();
orderGoodsItem.setOrderid(orderSummary.getId());
//拿到相對(duì)應(yīng)訂單號(hào)的所有商品
List<OrderGoodsItem> goodsList = orderGoodsMap.get(orderCode);
//如果goodsList為空,則新建;
//而且把這個(gè)訂單號(hào)的orderGoodsMap持有訂單的對(duì)象goodsList
if (goodsList == null) {
goodsList = new ArrayList<>();
orderGoodsMap.put(orderCode, goodsList);
}
//goodsList添加商品的對(duì)象,因?yàn)閛rderGoodsMap
//已經(jīng)持有這個(gè)訂單號(hào)的goodsList對(duì)象,所以不用重新put
goodsList.add(orderGoodsItem);
//把小訂單的店鋪信息賦給GoodsOrderInfo對(duì)象,并加入到orderInfoMap
GoodsOrderInfo orderInfo = orderInfoMap.get(orderCode);
if(orderInfo == null) {
orderInfo = new GoodsOrderInfo();
orderInfo.setOrderCode(orderCode);
orderInfo.setShopName(orderGoodsItem.getOrder().getShopName());
orderInfo.setStatus(orderGoodsItem.getOrder().getStatus());
orderInfoMap.put(orderCode, orderInfo);
}
}
//把所有數(shù)據(jù)按照頭部、內(nèi)容和尾部三個(gè)部分排序好
Set<String> keySet = orderGoodsMap.keySet();
for(String orderCode : keySet) {
dataList.add(orderInfoMap.get(orderCode));
dataList.addAll(orderGoodsMap.get(orderCode));
}
dataList.add(orderPayInfo);
}
return dataList;
}
}
代碼很簡單,只是一個(gè)簡單的工具類,就把后臺(tái)返回來的三層數(shù)據(jù)分為了一層,一條已經(jīng)排好序的List<Object>。
然后我們就去看看簡單的adapter數(shù)據(jù)顯示:
下面就是拿到數(shù)據(jù)之后的使用:
看看adapter怎么寫:
是不是很簡單?其實(shí)師兄的這種做法同時(shí)也利用了RecyclerView可以顯示返回不同的布局,然后通過三種不同的布局拼接來完成一層RecyclerView控制三層數(shù)據(jù)的相關(guān)做法,而且這樣做并不會(huì)用到該死的嵌套R(shí)ecyclerView,不會(huì)有那該死的不知道拿來的顯示bug,我個(gè)人覺得真的很贊!你們覺得如何?
感興趣的同學(xué)可以下載源碼去慢慢研究,有不同做法的同學(xué)可以提出來~
源碼下載鏈接