Android 仿淘宝京东等我的订单界面及任意列表拓展

概述

目前像淘宝及展示列表等都有多个item展示的需求,可能大多数如果没做过,第一眼就是ListView去嵌套ListView,虽然这样是可以完成,但是这样做会导致手机过度绘制,为什么呢?因为当一个Item加载的时候又会去更新item里面的adapter,apapter又会去更新自己的item,这样就会导致加载一条x*n耗时.
淘宝订单

解决思路

当我遇到这样的问题时候,其实我们可以把整个List,当做一个List处理,怎么做呢?其实就是一个复杂的ListView:
这里写图片描述

  • 头部分为一个type
  • 内容分为一个type
  • 顶部分为一个type

然后可以通过listview或者recyclerview的getItemViewTypegetViewTypeCount,特别注意一下,如果你使用了PulltoRefresh的ListView,那么就需要getViewTypeCount返回5(3+2),为什么呢,通过源码可以看到PullToRefreshListView也是add了Header.(自己可以看源码解决)

难点

难点其实在于对于服务器的数据的要求.一般服务器返回回来的数据都是一个List里面包含了多个List:

{
    "code": "0000",
    "desc": null,
    "token": "ad762d27-ced6-4092-b415-ddad8ee0b98e__1472123395714",
    "msg": [
        {
            "amount": 601,
            "consignee": "andrea",
            "address": "天府软件园A区",
            "orderItem": [ #列表数据
                {
                    "thumbnail": null,
                    "quantity": 1,
                    "price": 601,
                    "name": "熊猫座椅",
                    "id": 11
                }
            ],
            "freight": 0,
            "orderStatus": "unconfirmed",
            "productCount": 1,
            "shippingStatus": "unshipped",
            "phone": "15892999216",
            "areaName": "四川省成都市",
            "id": 9,
            "sn": "20160825202",
            "paymentStatus": "unpaid",
            "createDate": 1472123141000
        },
        {
            "amount": 601,
            "consignee": "andrea",
            "address": "天府软件园A区",
            "orderItem": [ #列表数据
                {
                    "thumbnail": null,
                    "quantity": 1,
                    "price": 601,
                    "name": "熊猫座椅",
                    "id": 10
                }
            ],
            "freight": 0,
            "orderStatus": "unconfirmed",
            "productCount": 1,
            "shippingStatus": "unshipped",
            "phone": "15892999216",
            "areaName": "四川省成都市",
            "id": 8,
            "sn": "20160825102",
            "paymentStatus": "unpaid",
            "createDate": 1472122855000
        }
    ],
    "page": {
        "total": 8,
        "pageNumber": 1,
        "pageSize": 2
    }
}

遇到这样数据,我们难道要求服务器的哥们帮我改改吗?如果不给改怎么办?当然可以解决了.怎么办呢?那我们就可以去拆分数据了,怎么拆呢?:

  • 把一个item拆分成三份.
  • 第一份 : 保留item关系且和需要展示的顶部数据.
  • 第二份 : 保留item关系且和需要展示购买列表数据.
  • 第三分 : 保留item关系且和需要展示顶部购买数量,价格,支付状态等展示或者按钮和文本

通过上面描述,基本说明了遇到的难点.

代码实现

我仅仅是贴出相关的核心代码:

    /**
     * 拆分订单
     *
     * @author Tanck
     * @param list
     * @return
     */
    private List<ShopOrderListResponse.MsgBean> handleList(List<ShopOrderListResponse.MsgBean> list) {
        if (null == list || 0 == list.size())
            return list;
        List<ShopOrderListResponse.MsgBean> temp = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {//拆解一个订单
            ++total;
            bean = list.get(i);
            bean.setType(1);//给bean增加了一个type字段,所以这样可以用来set,为了在adapter里面去判断是什么类型
            temp.add(bean);//先增加一个头
            for (int j = 0; j < list.get(i).getOrderItem().size(); j++) {//拆解一个订单里面的具体每个订单
                ++total;
                bean = (ShopOrderListResponse.MsgBean) bean.clone();//这里用了深拷贝,是因为要对数据进行修改,后面会给出连接.
                
                bean.setType(2);
                bean.setOrderPosition(j);
                temp.add(bean);//增加一个内容
            }
//            ++total;
            bean = (ShopOrderListResponse.MsgBean) bean.clone();
            bean.setType(3);
            temp.add(bean);//尾部添加一个
        }
        return temp;
    }

有了拆分后,那么就需要如何展示了.看看我的adapter吧:

    @Override
    public int getItemViewType(int position) {
        return list.get(position).getType();
    }

    @Override
    public int getViewTypeCount() {
        return 5;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {


        ViewHolder holder = null;

        if (null == convertView) {
            holder = new ViewHolder();
            switch (getItemViewType(position)) {
                case 1: // head
                    convertView = View.inflate(context, R.layout.item_shop_order_list_head, null);
                    holder.time = (TextView) convertView.findViewById(R.id.tv_item_order_time);
                    holder.status = (TextView) convertView.findViewById(R.id.tv_item_order_status);
                    holder.detailHead = (RelativeLayout) convertView.findViewById(R.id.rl_item_order_detail_head);
                    break;
                case 2:// content
                    convertView = View.inflate(context, R.layout.item_shop_order_list_content, null);
                    holder.icon = (ImageView) convertView.findViewById(R.id.iv_sp_my_order_item);
                    holder.orderMoney = (TextView) convertView.findViewById(R.id.tv_sp_my_order_money);
                    holder.number = (TextView) convertView.findViewById(R.id.tv_sp_my_order_number);
                    holder.orderName = (TextView) convertView.findViewById(R.id.tv_sp_my_order_name);
                    holder.content = (RelativeLayout) convertView.findViewById(R.id.rl_sp_my_order_content);
                    break;
                case 3: // bottom
                    convertView = View.inflate(context, R.layout.item_shop_order_list_bottom, null);
                    holder.money = (TextView) convertView.findViewById(R.id.tv_item_order_money);
                    holder.cancel = (TextView) convertView.findViewById(R.id.tv_item_order_cancel);
                    holder.pay = (TextView) convertView.findViewById(R.id.tv_item_order_pay);
                    holder.detailBottom = (LinearLayout) convertView.findViewById(R.id.ll_item_order_detail_bottom);
                    holder.opt = (RelativeLayout) convertView.findViewById(R.id.rl_item_order_opt);
                    holder.back = (TextView) convertView.findViewById(R.id.tv_item_order_back);
                    holder.backGoods = (TextView) convertView.findViewById(R.id.tv_item_order_back_goods);
                    break;
            }
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        String tempPayStatus = list.get(position).getPaymentStatus();
        String tempOrderStatus = list.get(position).getOrderStatus();
        String tempShippingStatus = list.get(position).getShippingStatus();
        holder.setListener(position);
        switch (getItemViewType(position)) {
            case 1:// head

                holder.time.setText(context.getString(R.string.order_time) + getDate(list.get(position).getCreateDate()));
                /**
                 * 订单状态
                 未确认
                 unconfirmed,

                 已确认
                 confirmed,

                 已完成
                 completed,

                 已取消
                 cancelled,

                 已失效
                 failure
                 */
                if ("failure".equals(tempOrderStatus)) {
                    holder.status.setText(R.string.time_out_close);
                } else if ("unpaid".equals(tempPayStatus) && "cancelled".equals(tempOrderStatus)) {
                    holder.status.setText(R.string.cancel_order);
                } else if ("unpaid".equals(tempPayStatus)) {
                    holder.status.setText(R.string.unpaid);
                } else if ("paid".equals(tempPayStatus) && "unconfirmed".equals(tempOrderStatus)) {
                    holder.status.setText(R.string.paid);
                } else if ("paid".equals(tempPayStatus) && "confirmed".equals(tempOrderStatus)) {
                    holder.status.setText(R.string.unsend);
                } else if ("shipped".equals(tempShippingStatus)) {
                    holder.status.setText(R.string.unrec);
                } else if ("received".equals(tempShippingStatus)) {
                    holder.status.setText(R.string.received);
                } else {
                    holder.status.setText(R.string.not_no);
                }
                holder.detailHead.setOnClickListener(holder);
                break;
            case 2:// content
                int tempP = list.get(position).getOrderPosition();//获取orderItem真实位置
                String iconString = list.get(position).getOrderItem().get(tempP).getThumbnail();
                if (StringUtil.isEmpty(iconString))
                    holder.icon.setScaleType(ImageView.ScaleType.FIT_XY);
                XUtilsImageLoader.getHomeAdvImg(context, R.drawable.udesk_defualt_failure, holder.icon, iconString);
                holder.orderName.setText(list.get(position).getOrderItem().get(tempP).getName());
                holder.number.setText("x" + list.get(position).getOrderItem().get(tempP).getQuantity());
                holder.orderMoney.setText("¥" + list.get(position).getOrderItem().get(tempP).getPrice());
                holder.content.setOnClickListener(holder);
                break;
            case 3://bottom
                holder.money.setText("共" + list.get(position).getProductCount() + "件商品 实付:¥" + list.get(position).getAmount());
                holder.detailBottom.setOnClickListener(holder);
                if ("failure".equals(tempOrderStatus)) {//交易关闭
                    holder.opt.setVisibility(View.GONE);
                } else if ("unpaid".equals(tempPayStatus) && "cancelled".equals(tempOrderStatus)) {//没给钱,点击已取消
                    holder.opt.setVisibility(View.GONE);
                } else if ("unpaid".equals(tempPayStatus)) {//待付款
                    holder.opt.setVisibility(View.VISIBLE);
                    // TODO 展示取消及付款,隐藏退货,退款
                    holder.pay.setVisibility(View.VISIBLE);
                    holder.cancel.setVisibility(View.VISIBLE);
                    holder.back.setVisibility(View.GONE);
                    holder.backGoods.setVisibility(View.GONE);
                    holder.pay.setOnClickListener(holder);
                    holder.cancel.setOnClickListener(holder);
                } else if ("paid".equals(tempPayStatus) && "unconfirmed".equals(tempOrderStatus)) {//给了钱,没确认
                    holder.opt.setVisibility(View.VISIBLE);
                    // TODO 展示退款,隐藏取消及付款,退货
                    holder.cancel.setVisibility(View.GONE);
                    holder.pay.setVisibility(View.GONE);
                    holder.backGoods.setVisibility(View.GONE);
                    holder.back.setVisibility(View.VISIBLE);
                    holder.back.setOnClickListener(holder);
                } else if ("paid".equals(tempPayStatus) && "confirmed".equals(tempOrderStatus)) {//给了钱,且确认了
                    holder.opt.setVisibility(View.VISIBLE);
                    // TODO 展示退款,隐藏取消及付款,退货
                    holder.cancel.setVisibility(View.GONE);
                    holder.pay.setVisibility(View.GONE);
                    holder.back.setVisibility(View.VISIBLE);
                    holder.backGoods.setVisibility(View.GONE);
                    holder.back.setOnClickListener(holder);
                } else if ("shipped".equals(tempShippingStatus)) {//待收货
                    holder.opt.setVisibility(View.VISIBLE);
                    // TODO 展示退款,隐藏取消及付款,退货(后期可能会增加查看物流)
                    holder.cancel.setVisibility(View.GONE);
                    holder.pay.setVisibility(View.GONE);
                    holder.backGoods.setVisibility(View.GONE);
                    holder.back.setVisibility(View.VISIBLE);
                    holder.back.setOnClickListener(holder);
                } else if ("received".equals(tempShippingStatus)) {//收货了,待评价
                    holder.opt.setVisibility(View.VISIBLE);
                    // TODO 展示退货,隐藏取消及付款,退款
                    holder.back.setVisibility(View.GONE);
                    holder.cancel.setVisibility(View.GONE);
                    holder.pay.setVisibility(View.GONE);
                    holder.backGoods.setVisibility(View.VISIBLE);
                    holder.backGoods.setOnClickListener(holder);
                } else { // 等待确认
                    holder.opt.setVisibility(View.GONE);
                }

                break;
        }

        return convertView;
    }

原型模式学习(参考这儿)

总结

我们可以用一个ListView或者RecyclerView去做很多复杂类型的,为什么这样做不卡?因为自带了复用机制,复用机制的话这里就不用多说了.所以经过这样我们就可以随意做复杂的列表而且不卡顿.

Demo地址:Demo地址

评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值