android優雅的解決列表巢狀 類似訂單列表這種
阿新 • • 發佈:2019-01-29
常見問題,類似訂單列表這種,每個大item,有相同佈局,但有些頭部和底部View沒辦法根據資料型別複用,如下圖。很多人採用列表巢狀列表來做,但這樣會造成UI卡頓,因為滑動的時候外層列表的Item需不斷的去設定內層列表的adapter。
機智的我覺得肯定是有辦法,通過一個ListView或RecyclerView有多種item佈局來實現。
通常後端返回資料是array裡面嵌套了array。
{
data:[
{//大item
order_num:"5236872983023",
products:[
{//小item
product_id:"352787398209380"
}
]
}
]
}
想要用一個ListView或RecyclerView有多種item佈局來實現,那資料必須是一個List。那我們為什麼不把後端返回的資料,重新包裝下呢。
思路:
按照UI結構,有頭部、中間子列表item、底部三種佈局型別,那就要三種資料型別。
然而後端返回的資料中並沒有頭部和底部這兩種資料,那麼我們可以去偽造出這兩種資料,我們可以把後端返回的資料提取出來然後增加頭部和底部資料裝進一個List容器中。
我們可以自定義一個類:
/**
* 類似訂單列表 每個大item有相同頭部底部佈局,中間小item列表
* 二次封裝資料 解決列表巢狀 避免UI卡頓
* Created by hucanhui on 2017/2/28.
*/
public class MultipleTypeDataHelper {
public List<MultipleTypeData> datas = new ArrayList<MultipleTypeData>();//二次封裝的資料容器
public void add(MultipleTypeData multipleTypeData){
datas.add(multipleTypeData);
}
public void remove(MultipleTypeData multipleTypeData){
datas.remove(multipleTypeData);
}
public void remove(int index){
datas.remove(index);
}
/**
* 新增不同型別的資料
* @param type 資料型別
* @param object 對應資料
*/
public void add(int type, Object object){
MultipleTypeData multipleTypeData = new MultipleTypeData();
multipleTypeData.setData(object);
multipleTypeData.setType(type);
add(multipleTypeData);
}
public List<MultipleTypeData> getDatas() {
return datas;
}
public void setDatas(List<MultipleTypeData> datas) {
this.datas = datas;
}
class MultipleTypeData{
private int type;//自行定好 type值對應的型別
private Object data;//資料 大items資料 或小item資料
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
}
程式碼有註釋略看應該就懂。
然後我們,用for迴圈遍歷後端返回的資料,add到這個到這個容器中,按照UI結構順序,因先新增頭部的資料,然後再新增中間列表item的資料,最後新增底部的資料。示例:
List<List> listList = new ArrayList<>();//假設這是後端返回資料
MultipleTypeDataHelper helper = new MultipleTypeDataHelper();
//二次資料封裝示例 根據後端返回資料結構自行調整 這邊只是個思路
int outSize = listList.size();
for (int i = 0; i < outSize; i++) {
List list = listList.get(i);
helper.add(1, list);//大item頭部 型別為1
int innerSize = list.size();
for (int j = 0; j < innerSize; j++) {
helper.add(2, list.get(i));//中間小item
}
helper.add(3, list);//底部
}
我們已經把所有佈局的資料按順序放進一個List裡面了,這下應該就非常好辦了吧,不管你用ListView還是RecyclerView,在Adapter中根據List中取出資料的型別返回對於佈局就好。以RecyclerView為例:
@Override
public int getItemViewType(int position) {
return help.datas.get(position).getType();//返回對應型別
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = null;
switch (viewType){//這裡根據不同型別建立ViewHolder
case 1:
break;
case 2:
break;
case 3:
break;
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
int type = getItemViewType(position);
switch (type){//根據不同型別繫結holder
case 1:
break;
case 2:
break;
case 3:
break;
}
Game Over! 大家可根據實際開發情況改,最重要的一個是拼裝資料。其實一些有時間軸做頭部的列表,也可以用類似的做法,集思廣益。