Android ListView多布局讲解

Posted tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android ListView多布局讲解相关的知识,希望对你有一定的参考价值。

 Listview优化是一个老生常谈的事情了,其优化的方面也有很多种,例如,布局重用、在getView()中减少逻辑计算、减少在页面滑动的时候加在图片,而是在页面停止滚动的时候再加在图片。而今天要介绍的是另一种方式,那就是多布局。

一般使用的场景有一下两种情况:

① 当一个item有多重布局的情况下,使用部分隐藏来实现既笨拙又效率低下,这时多布局会是个不错的选择;

② 当一个item很复杂,页面内容多,item高度很高,甚至超过手机屏幕,这个时候就需要使用多布局将页面拆分成多个小item来提高执行效率。

举个栗子:如下销售订单列表,我们发现一个单个item的页面高度很高,内容也很多,中部的商品个数还具有不确定性,这时的实现的方式我们可以看下:

 代码如下:

 1 @Override
 2 public View getView(final int position, View convertView, ViewGroup rootview) {
 3      ViewHolder viewHolder = null;
 4      if (convertView == null) {
 5          viewHolder = new ViewHolder();
 6          convertView = inflater.inflate(R.layout.item_list_order, rootview, false);
 7          // ...
 8          convertView.setTag(viewHolder);
 9      } else {
10          viewHolder = (ViewHolder) convertView.getTag();
11      }
12  
13      for (int i = 0; i < arrListOrder.get(position).size(); i++) {
14          View v = inflater.inflate(R.layout.item_order_goods, null);
15          // ...
16          viewHolder.llayoutGoodsList.addView(v);
17      }
18  
19      // ...
20      return convertView;
21 }

 

这种写法诟病很大,严重影响性能,此外如果商品数量有个10个8个的会导致item过高,此外在getView()中for循环new布局对象是是否消耗内存的和执行时间的。

 

那么,我们用多布局拆分下:

 

 

这种布局方式就叫ListView的多布局。采用将一个大的 item 切割成多个小item以降低布局的复杂度,提高重用率。那么直接看这种方式的实现方式:

 

 1 public class OrderListActivity extends Activity {
 2     // ...
 3 
 4     /** 解析请求数据 */
 5     private ArrayList<HashMap<String, Object>> analyticalData(String json) {
 6         ArrayList<HashMap<String, Object>> arrListGoods = new ArrayList<>();
 7         try {
 8             JSONArray jsArr = new JSONArray(json);
 9             for (int i = 0; i < jsArr.length(); i++) {
10                 JSONObject jsObj = jsArr.optJSONObject(i);
11                 // 头部
12                 hashMapHead.put("order_sn", jsObj.optString("order_sn")); // 销售订单号
13                 // ...
14                 hashMapHead.put("item_type", OrderListAdapter.NI_ORDER_ITEM_HEAD); // 设置布局类型
15                 arrListGoods.add(hashMapHead);
16 
17                 // 商品
18                 JSONArray arrJsonGoods = jsObj.getJSONArray("order_goods");
19                 JSONObject jsobjPay = new JSONObject();
20                 for (int j = 0; j < arrJsonGoods.length(); i++) {
21                     HashMap<String, Object> hashMapGoods = new HashMap<>();
22                     hashMapHead.put("goods_name", jsObj.optString("goods_name")); //商品名
23                     // ...
24                     hashMapHead.put("item_type", OrderListAdapter.NI_ORDER_ITEM_GOODS);
25                     arrListGoods.add(hashMapGoods);
26                 }
27 
28                 // 底部
29                 HashMap<String, Object> hashMapFoot = new HashMap<>();
30                 hashMapFoot.put("address", jsObj.optString("address")); // 地址
31                 // ... 
32                 hashMapHead.put("item_type", OrderListAdapter.NI_ORDER_ITEM_FOOT);
33                 arrListGoods.add(hashMapFoot);
34             }
35         } catch (JSONException e) {
36             return null;
37         }
38         return arrListGoods;
39     }
40 }

 

 1 public class OrderListAdapter extends BaseAdapter {
 2 
 3     public static final int NI_ORDER_ITEM_HEAD = 0; // 这要从0按顺序往下变化,否则报错“数组下标溢出”,原因还不清楚
 4     public static final int NI_ORDER_ITEM_GOODS = 1;
 5     public static final int NI_ORDER_ITEM_FOOT = 2;
 6 
 7     // ...
 8     /** 获取布局的类型 */
 9     @Override
10     public int getItemViewType(int position) {
11         try {
12             int i = Integer.parseInt(mAppList.get(position).get("item_type").toString());
13             switch (i){
14                 case NI_ORDER_ITEM_HEAD:
15                 case NI_ORDER_ITEM_GOODS:
16                 case NI_ORDER_ITEM_FOOT:
17                     return i;
18             }
19         } catch (Exception e) {
20         }
21         return super.getItemViewType(position);
22     }
23     /** 获取布局类型的总数 */
24     @Override
25     public int getViewTypeCount() {
26         return 3;
27     }
28 
29     @Override
30     public View getView(int position, View convertView, ViewGroup rootview) {
31         ViewHolder viewHolderHead = null;
32         ViewHolder viewHolderGoods = null;
33         ViewHolder viewHolderFoot = null;
34         int type = getItemViewType(position);
35         if (convertView == null) {
36             switch(type){
37                 case NI_ORDER_ITEM_HEAD:
38                     viewHolderHead = new viewHolderHead();
39                     convertView = mInflater.inflate(R.layout.item_list_order_head, rootview, false);
40                     // ...初始化布局
41                     convertView.setTag(R.layout.item_list_order_head, viewHolderHead); // 这里要用setTag(int, Object);
42                     break;
43                 case NI_ORDER_ITEM_GOODS:
44                     viewHolderGoods = new viewHolderGoods();
45                     convertView = mInflater.inflate(R.layout.item_list_order_goods, rootview, false);
46                     // ...初始化布局
47                     convertView.setTag(R.layout.item_list_order_goods, viewHolderGoods);
48                     break;
49                 case NI_ORDER_ITEM_FOOT: 
50                     viewHolderFoot = new viewHolderFoot();
51                     convertView = mInflater.inflate(R.layout.item_list_order_foot, rootview, false);
52                     // ...初始化布局
53                     convertView.setTag(R.layout.item_list_order_foot, viewHolderFoot);
54                     break;
55             }
56         } else {
57             switch(type){
58                 case NI_ORDER_ITEM_HEAD:
59                     viewHolderHead = getTag(R.layout.item_list_order_head);
60                     break;
61                 case NI_ORDER_ITEM_GOODS:
62                     viewHolderGoods = getTag(R.layout.item_list_order_goods);
63                     break;
64                 case NI_ORDER_ITEM_FOOT:
65                     viewHolderFoot = getTag(R.layout.item_list_order_foot);
66                     break;
67             }
68         }
69         switch(type){
70             case NI_ORDER_ITEM_HEAD:
71                 // ...处理逻辑
72                 break;
73             case NI_ORDER_ITEM_GOODS:
74                 // ...
75                 break;
76             case NI_ORDER_ITEM_FOOT:
77                 // ...
78                 break;
79         }
80         return convertView;
81     }
82 
83     private class ViewHolderHead {
84         // ...
85     }
86     private class ViewHolderGoods {
87        // ...
88     }
89     private class ViewHolderFoot {
90         // ...
91     }
92 
93     // ...
94 }

 

好,到这里就介绍完了,活用多布局,对提高Listview的执行效率是很有帮助的。

 

以上是关于Android ListView多布局讲解的主要内容,如果未能解决你的问题,请参考以下文章

Android:滚动整个片段,里面有 ListView

片段中 ListView 的 setOnItemClickListener

android样式布局---&gt;ListView(附上源代码)

ListView Item多布局的实现

片段中ListView的setOnItemClickListener

ListView布局高度与Fragment中的RecyclerView内的父级不匹配