Android二级购物车(带商家)的简单实现

本文通过MVP架构详细介绍了如何在Android应用中实现一个带有商家信息的二级购物车功能,包括依赖导入、接口定义、视图接口、适配器和店铺信息Bean类的创建,以及必要的布局和权限配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天我们要用MVP实现一个二级购物车(带商家的购物车)废话不多说,直接上代码

首先我们需要进行依赖的导入

    compile 'com.facebook.fresco:fresco:1.5.0'
    compile 'com.android.support:recyclerview-v7:26.0.0-alpha1'
    compile 'com.jakewharton:butterknife:7.0.1'
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    compile 'io.reactivex.rxjava2:rxjava:2.1.7'
    compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
    compile files('libs/universal-image-loader-1.9.3-with-sources.jar')   //这个是imageloader的jar包

依赖导完我们先进行网络请求数据地址的拆分

定义一个接口,用注解的形式来拆分

public interface IInterface {

    @POST
    Observable<Selectshop> get(@Url() String url, @QueryMap Map<String,String> map);

}


然后定义一个类继承application用来进行初始化

public class IApplication extends Application {

    public static IInterface iInterface;

    @Override
    public void onCreate() {
        super.onCreate();
        Fresco.initialize(this); //Fresco图片加载的初始化
        ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(this).build();
        ImageLoader.getInstance().init(configuration);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://120.27.23.105/") //这里写接口前段的域名
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

        iInterface = retrofit.create(IInterface.class);

    }
}

接着我们来实现用MVP请求数据

首先定义一个view层的接口

public interface ShopcarView {

    void getshopcar(List<Selectshop.DataBean> data);

}

再定义一个model层的接口

public interface ShopcarModel {
   
   

    void getjson(String url,String uid);

}

定义一个类用来实现model接口

public class MyShopcarModel implements ShopcarModel {
    Getselectshop getselectshop;
    public interface Getselectshop{
        void SelectshopListener(List<Selectshop.DataBean> data);
    }
    public void SetselectshopListener(Getselectshop getselectshop){
        this.getselectshop=getselectshop;
    }
    @Override
    public void getjson(String url, String uid) {
        Map<String,String> map = new HashMap<>();
        map.put("uid",uid);		//必传的参数
        map.put("source","android");   //公共参数
        IApplication.iInterface.get(url,map)
        .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Selectshop>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull Selectshop selectshop) {
                        getselectshop.SelectshopListener(selectshop.getData());
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }
}

presenter层实现model层

public class ShopcarPresenter implements MyShopcarModel.Getselectshop {
    private MyShopcarModel shopcarm;
    private ShopcarView ishopcarview;
    public ShopcarPresenter(ShopcarView ishopcarview) {
        this.ishopcarview = ishopcarview;
        this.shopcarm =new MyShopcarModel();
        shopcarm.SetselectshopListener(this);
    }
    public void Seturl(String url,String uid)
    {
        shopcarm.getjson(url,uid);
    }

    @Override
    public void SelectshopListener(List<Selectshop.DataBean> data) {
        ishopcarview.getshopcar(data);
    }
}

MVP实现后贴出MainActivity的代码

public class MainActivity extends AppCompatActivity implements ShopcartAdapter.CheckInterface,
        ShopcartAdapter.GroupEdtorListener, ShopcartAdapter.ModifyCountInterface , ShopcarView {

    @Bind(R.id.back)
    ImageView back;
    @Bind(R.id.title)
    TextView title;
    @Bind(R.id.subtitle)
    TextView subtitle;
    @Bind(R.id.top_bar)
    LinearLayout topBar;
    @Bind(R.id.exListView)
    ExpandableListView exListView;
    @Bind(R.id.all_chekbox)
    CheckBox allChekbox;
    @Bind(R.id.tv_total_price)
    TextView tvTotalPrice;
    @Bind(R.id.tv_go_to_pay)
    TextView tvGoToPay;
    @Bind(R.id.ll_info)
    LinearLayout llInfo;
    @Bind(R.id.tv_share)
    TextView tvShare;
    @Bind(R.id.tv_save)
    TextView tvSave;
    @Bind(R.id.tv_delete)
    TextView tvDelete;
    @Bind(R.id.ll_shar)
    LinearLayout llShar;

    private double totalPrice = 0.00;// 购买的商品总价
    private int totalCount = 0;// 购买的商品总数量
    private ShopcartAdapter selva;
    private List<StoreInfo> groups = new ArrayList<StoreInfo>();// 组元素数据列表
    private Map<String, List<GoodsInfo>> children = new HashMap<String, List<GoodsInfo>>();// 子元素数据列表
    private int flag = 0;
    private List<GoodsInfo> products;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        ShopcarPresenter presenter = new ShopcarPresenter(this);
        presenter.Seturl("product/getCarts", "71"); //第一个参数是地址域名后参数前的字段,第二个参数是必须要上传的用户名

    }

    @Override
    public void getshopcar(List<Selectshop.DataBean> data) {
        for (int i = 0; i < data.size(); i++) {
            groups.add(new StoreInfo(data.get(i).getSellerid(), data.get(i).getSellerName()));
            products = new ArrayList<GoodsInfo>();
            for (int j = 0; j < data.get(i).getList().size(); j++) {
                String images = data.get(i).getList().get(j).getImages();
                String[] split = images.split("[|]");
                String[] split1 = split[0].split("[!]");
                List<Selectshop.DataBean.ListBean> list = data.get(i).getList();
                products.add(new GoodsInfo(list.get(j).getPid() + "", "商品", list.get(j).getTitle(),Double.valueOf(list.get(j).getPrice()+""), Integer.parseInt(list.get(j).getNum()+""), "", "1", split1[0],Double.valueOf(list.get(j).getBargainPrice())));
            }
            children.put(groups.get(i).getId(), products);// 将组元素的一个唯一值,这里取Id,作为子元素List的Key
        }
        initEvents();
    }

    private void initEvents() {
        selva = new ShopcartAdapter(groups, children, this);
        selva.setCheckInterface(this);// 关键步骤1,设置复选框接口
        selva.setModifyCountInterface(this);// 关键步骤2,设置数量增减接口
        selva.setmListener(this);
        exListView.setAdapter(selva);
        for (int i = 0; i < selva.getGroupCount(); i++) {
            exListView.expandGroup(i);// 关键步骤3,初始化时,将ExpandableListView以展开的方式呈现
        }
    }


    @Override
    public void checkGroup(int groupPosition, boolean isChecked) {
        StoreInfo group = groups.get(groupPosition);
        List<GoodsInfo> childs = children.get(group.getId());
        for (int i = 0; i < childs.size(); i++) {
            childs.get(i).setChoosed(isChecked);
        }
        if (isAllCheck())
            allChekbox.setChecked(true);
        else
            allChekbox.setChecked(false);
        selva.notifyDataSetChanged();
        calculate();
    }

    private void calculate() {
        totalCount = 0;
        totalPrice = 0.00;
        for (int i = 0; i < groups.size(); i++) {
            StoreInfo group = groups.get(i);
            List<GoodsInfo> childs = children.get(group.getId());
            for (int j = 0; j < childs.size(); j++) {
                GoodsInfo product = childs.get(j);
                if (product.isChoosed()) {
                    totalCount++;
                    totalPrice += product.getPrice() * product.getCount();
                }
            }
        }
        tvTotalPrice.setText("¥" + totalPrice);
        tvGoToPay.setText("去支付(" + totalCount + ")");
    }

    private boolean isAllCheck() {

        for (StoreInfo group : groups) {
            if (!group.isChoosed())
                return false;
        }
        return true;
    }

    @Override
    public void checkChild(int groupPosition, int childPosition, boolean isChecked) {
        boolean allChildSameState = true;// 判断改组下面的所有子元素是否是同一种状态
        StoreInfo group = groups.get(groupPosition);
        List<GoodsInfo> childs = children.get(group.getId());
        for (int i = 0; i < childs.size(); i++) {
            // 不全选中
            if (childs.get(i).isChoosed() != isChecked) {
                allChildSameState = false;
                break;
            }
        }
        //获取店铺选中商品的总金额
        if (allChildSameState) {
            group.setChoosed(isChecked);// 如果所有子元素状态相同,那么对应的组元素被设为这种统一状态
        } else {
            group.setChoosed(false);// 否则,组元素一律设置为未选中状态
        }
        if (isAllCheck()) {
            allChekbox.setChecked(true);// 全选
        } else {
            allChekbox.setChecked(false);// 反选
        }
        selva.notifyDataSetChanged();
        calculate();
    }

    @OnClick({R.id.all_chekbox, R.id.tv_delete, R.id.tv_go_to_pay, R.id.subtitle, R.id.tv_save, R.id.tv_share})
    public void onClick(View view) {
        AlertDialog alert;
        switch (view.getId()) {
            case R.id.all_chekbox:
                doCheckAll();
                break;
            case R.id.tv_delete:
                if (totalCount == 0) {
                    Toast.makeText(this, "请选择要移除的商品", Toast.LENGTH_LONG).show();
                    return;
                }
                alert = new AlertDialog.Builder(this).create();
                alert.setTitle("操作提示");
                alert.setMessage("您确定要将这些商品从购物车中移除吗?");
                alert.setButton(DialogInterface.BUTTON_NEGATIVE, "取消",
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                return;
                            }
                        });
                alert.setButton(DialogInterface.BUTTON_POSITIVE, "确定",
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                doDelete();
                            }
                        });
                alert.show();
                break;
            case R.id.tv_go_to_pay:
                if (totalCount == 0) {
                    Toast.makeText(this, "请选择要支付的商品", Toast.LENGTH_LONG).show();
                    return;
                }
                alert = new AlertDialog.Builder(this).create();
                alert.setTitle("操作提示");
                alert.setMessage("总计:\n" + totalCount + "种商品\n" + totalPrice + "元");
                alert.setButton(DialogInterface.BUTTON_NEGATIVE, "取消",
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                return;
                            }
                        });
                alert.setButton(DialogInterface.BUTTON_POSITIVE, "确定",
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                            }
                        });
                alert.show();
                break;
            case R.id.subtitle:
                if (flag == 0) {
                    llInfo.setVisibility(View.GONE);
                    tvGoToPay.setVisibility(View.GONE);
                    llShar.setVisibility(View.VISIBLE);
                    subtitle.setText("完成");
                } else if (flag == 1) {
                    llInfo.setVisibility(View.VISIBLE);
                    tvGoToPay.setVisibility(View.VISIBLE);
                    llShar.setVisibility(View.GONE);
                    subtitle.setText("编辑");
                }
                flag = (flag + 1) % 2;//其余得到循环执行上面2个不同的功能
                break;
            case R.id.tv_share:
                if (totalCount == 0) {
                    Toast.makeText(this, "请选择要分享的商品", Toast.LENGTH_LONG).show();
                    return;
                }
                Toast.makeText(this, "分享成功", Toast.LENGTH_SHORT).show();
                break;
            case R.id.tv_save:
                if (totalCount == 0) {
                    Toast.makeText(this, "请选择要保存的商品", Toast.LENGTH_LONG).show();
                    return;
                }
                Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show();
                break;
        }
    }

    private void doDelete() {
        List<StoreInfo> toBeDeleteGroups = new ArrayList<StoreInfo>();// 待删除的组元素列表
        for (int i = 0; i < groups.size(); i++) {
            StoreInfo group = groups.get(i);
            if (group.isChoosed()) {
                toBeDeleteGroups.add(group);
            }
            List<GoodsInfo> toBeDeleteProducts = new ArrayList<GoodsInfo>();// 待删除的子元素列表
            List<GoodsInfo> childs = children.get(group.getId());
            for (int j = 0; j < childs.size(); j++) {
                if (childs.get(j).isChoosed()) {
                    toBeDeleteProducts.add(childs.get(j));
                }
            }
            childs.removeAll(toBeDeleteProducts);
        }
        groups.removeAll(toBeDeleteGroups);
        calculate();
        selva.notifyDataSetChanged();
    }

    private void doCheckAll() {
        for (int i = 0; i < groups.size(); i++) {
            groups.get(i).setChoosed(allChekbox.isChecked());
            StoreInfo group = groups.get(i);
            List<GoodsInfo> childs = children.get(group.getId());
            for (int j = 0; j < childs.size(); j++) {
                childs.get(j).setChoosed(allChekbox.isChecked());
            }
        }
        calculate();
        selva.notifyDataSetChanged();
    }

    @Override
    public void groupEdit(int groupPosition) {
        groups.get(groupPosition).setIsEdtor(true);
        selva.notifyDataSetChanged();
    }

    @Override
    public void doIncrease(int groupPosition, int childPosition, View showCountView, boolean isChecked) {
        GoodsInfo product = (GoodsInfo) selva.getChild(groupPosition,
                childPosition);
        int currentCount = product.getCount();
        currentCount++;
        product.setCount(currentCount);
        ((TextView) showCountView).setText(currentCount + "");
        calculate();
        selva.notifyDataSetChanged();
    }

    @Override
    public void doDecrease(int groupPosition, int childPosition, View showCountView, boolean isChecked) {
        GoodsInfo product = (GoodsInfo) selva.getChild(groupPosition,
                childPosition);
        int currentCount = product.getCount();
        if (currentCount == 1)
            return;
        currentCount--;
        product.setCount(currentCount);
        ((TextView) showCountView).setText(currentCount + "");
        calculate();
        selva.notifyDataSetChanged();
    }

    @Override
    public void childDelete(int groupPosition, int childPosition) {
        children.get(groups.get(groupPosition).getId()).remove(childPosition);
        StoreInfo group = groups.get(groupPosition);
        List<GoodsInfo> childs = children.get(group.getId());
        if (childs.size() == 0) {
            groups.remove(groupPosition);
        }
        selva.notifyDataSetChanged();
        handler.sendEmptyMessage(0);
    }

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //删除购物车后动态改变数量
            setCartNum();
        }
    };

    private void setCartNum() {
        int count = 0;
        for (int i = 0; i < groups.size(); i++) {
            groups.get(i).setChoosed(allChekbox.isChecked());
            StoreInfo group = groups.get(i);
            List<GoodsInfo> childs = children.get(group.getId());
            for (GoodsInfo goodsInfo : childs) {
                count += 1;
            }
        }
        title.setText("购物车" + "(" + count + ")");
    }

}

然后需要两个适配器进行适配

首先是一个二次列表的适配器

public class ShopcartAdapter extends BaseExpandableListAdapter {
    private List<StoreInfo> groups;
    private Map<String, List<GoodsInfo>> children;
    private Context context;
    private CheckInterface checkInterface;
    private ModifyCountInterface modifyCountInterface;
    private int flag = 0;
   private GroupEdtorListener mListener;

    public GroupEdtorListener getmListener() {
        return mListener;
    }

    public void setmListener(GroupEdtor
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值