MVP+Rxjava+Retrofit实现二级列表购物车

效果:
在这里插入图片描述

1:build.gradle中导入依赖

implementation 'com.squareup.okhttp3:okhttp:3.9.0'
implementation 'com.google.code.gson:gson:2.8.5'
 implementation 'com.squareup.retrofit2:retrofit:2.4.0'
 implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
 implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
 implementation 'com.facebook.fresco:fresco:0.14.1'
 implementation 'io.reactivex.rxjava2:rxjava:2.1.7'
 implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
 implementation 'com.jcodecraeer:xrecyclerview:1.2.0'
 implementation 'com.android.support:recyclerview-v7:28.0.0'
 implementation 'com.github.bumptech.glide:glide:4.8.0'
 annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
 implementation 'com.jakewharton:butterknife:8.8.1'
 annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'


2:AndroidManifest.xml清单文件中加入网络权限

<uses-permission android:name="android.permission.INTERNET"/>

3:整体架构

在这里插入图片描述

4:创建一个类实现接口拼接

1:public class StringUrl {
    public static final String BASE_URL="http://www.zhaoapi.cn/";
}
2:public interface ApiService {
    //全部网址:http://www.zhaoapi.cn/product/getCarts?uid=71
    @GET("product/getCarts?uid=71")
    Observable<Cart> getCarts();
}

5:工具类Retrofitutils

public class RetrofitUtils {
    //支持RxJava
    public static ApiService getNetDatas(){ //这里的ApiService是拼接网址的接口名
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(5, TimeUnit.SECONDS)
                .readTimeout(5, TimeUnit.SECONDS)
                .build();

        Retrofit retrofit = new Retrofit.Builder()
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .client(client)
                .baseUrl(StringUrl.BASE_URL)
                .build();

        ApiService api = retrofit.create(ApiService.class);

        return api;
    }
}

6:创建bean类

网址:http://www.zhaoapi.cn/product/getCarts?uid=71

7:MVP框架搭建

1:view层**
		public interface CartView {
	    void getCart(Cart cart);
	    void faild(Exception e);
	
		}

2:model层

	2.1:
	public interface CartModel {
	    void cartrecy(Observer observer);
	}
	2.2:
		public class MyCartModel implements CartModel{
	
	    @Override
	    public void cartrecy(Observer observer) {
	        RetrofitUtils.getNetDatas().getCarts()
	                .subscribeOn(Schedulers.io())
	                .observeOn(AndroidSchedulers.mainThread())
	                .subscribe( observer);
	    }
	}

3.presenter层

public class CartPresenter {
    private CartView view;
    private CartModel model;


    public CartPresenter(CartView view) {
        this.view = view;
        model = new MyCartModel();
    }

    public void showCart(){
        model.cartrecy(new Observer<Cart>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(Cart cart) {
                view.getCart(cart);
            }
            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });
    }
    //解绑
    public void onDstory(){
        view = null;
    }
}



8:初始化全局的application在AndroidManifest.xml中加入name属性

public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Fresco.initialize(this);
    }
}

9:购物车加减器的布局

<TextView
        android:background="#ffffff"
        android:layout_weight="1"
        android:id="@+id/sub_tv"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:padding="10dp"
        android:text="-"
        android:textSize="20sp" />

    <TextView
        android:text="1"
        android:layout_marginLeft="2dp"
        android:background="#ffffff"
        android:layout_weight="1"
        android:id="@+id/product_number_tv"
        android:layout_width="0dp"
        android:padding="10dp"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:gravity="center"
        />

    <TextView
        android:layout_marginLeft="2dp"
        android:layout_weight="1"
        android:id="@+id/add_tv"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:gravity="center"
        android:text="+"
        android:textSize="20sp" />

10:购物车的加减器使用自定义组合控件使用

public class MyAddSubView extends LinearLayout implements View.OnClickListener {
    private int number = 1;
    private TextView sub_tv;
    private TextView product_number_tv;
    private TextView add_tv;

    public MyAddSubView(Context context) {
        this(context, null);
    }

    public MyAddSubView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyAddSubView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        View view = inflate(context, R.layout.add_remove_view_layout, this);

        sub_tv = view.findViewById(R.id.sub_tv);
        product_number_tv = view.findViewById(R.id.product_number_tv);
        add_tv = view.findViewById(R.id.add_tv);


        sub_tv.setOnClickListener(this);
        add_tv.setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.sub_tv:
                if (number > 1) {
                    --number;
                    product_number_tv.setText(number + "");
                    if (onNumberChangeListener != null) {
                        onNumberChangeListener.onNumberChange(number);
                    }
                } else {
                    Toast.makeText(getContext(), "不能再少了", Toast.LENGTH_SHORT).show();
                }
                break;


            case R.id.add_tv:
                ++number;
                product_number_tv.setText(number + "");
                if (onNumberChangeListener != null) {
                    onNumberChangeListener.onNumberChange(number);
                }
                break;
        }
    }


    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
        product_number_tv.setText(number + "");
    }

    OnNumberChangeListener onNumberChangeListener;

    public void setOnNumberChangeListener(OnNumberChangeListener onNumberChangeListener) {
        this.onNumberChangeListener = onNumberChangeListener;
    }

    public interface OnNumberChangeListener {
        void onNumberChange(int num);
    }
}


11:写适配器

因为是一个二级联动的购物车
1:一级列表布局
在这里插入图片描述

 <CheckBox
        android:id="@+id/cb_sj"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"/>
    <TextView
        android:id="@+id/txt_sj_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:padding="10dp"
        />

2:二级列表布局
在这里插入图片描述

<CheckBox
        android:id="@+id/cb_shop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"/>
    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/sdv_image"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginLeft="10dp"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_marginLeft="10dp"
        android:orientation="vertical">
        <TextView
            android:id="@+id/txt_shopname"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"/>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal">
            <TextView
                android:id="@+id/txt_shopprice"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:text="¥:0.0"
                android:gravity="center"
                android:textColor="#f73838"
                android:layout_weight="1"/>
            <com.bwie.newmoth01.utils.MyAddSubView
                android:id="@+id/subview"
                android:layout_width="0dp"
                android:gravity="center"
                android:layout_height="wrap_content"
                android:padding="10dp"
                android:layout_weight="1"></com.bwie.newmoth01.utils.MyAddSubView>
        </LinearLayout>
    </LinearLayout>

3:因为网址的图片是拼接的所以我们要进行截取,写一个类截取图片,适配器中使用

public class ImgProcess {
    public static String getImg(String images) {
        String[] a = images.split("\\|");
        return a[0];
    }
    public static String setImg(String images) {
        String a = images.replace("https","http");
        return a;
    }
}

:4:适配器adapter继承BaseExpandableListAdapter*

public class CartAdapter extends BaseExpandableListAdapter {
    private List<Cart.DataBean> dataBeanList;

    public CartAdapter(List<Cart.DataBean> dataBeanList) {
        this.dataBeanList = dataBeanList;
    }

    @Override
    public int getGroupCount() {
        return dataBeanList == null ? 0 : dataBeanList.size();
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        return dataBeanList.get(groupPosition).getList() == null ? 0 : dataBeanList.get(groupPosition).getList().size();
    }

    @Override
    public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
        Cart.DataBean dataBean = dataBeanList.get(groupPosition);
        ViewHolder1 holder1;
        if (convertView ==null){
            convertView = View.inflate(parent.getContext(),R.layout.cart_recy_one,null);
            holder1 = new ViewHolder1(convertView);
            convertView.setTag(holder1);
        }else {
            holder1 = (ViewHolder1) convertView.getTag();
        }
        //获取商家的名称
        holder1.sJname.setText(dataBean.getSellerName());

        //判断当前商家是否是选中状态
        boolean allSjShopselected = isAllSjShopselected(groupPosition);
        holder1.sJcb.setChecked(allSjShopselected);

        //设置点击复选框
        holder1.sJcb.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mOnCartListener !=null){
                    mOnCartListener.onCartSjChecked(groupPosition);
                }
            }
        });

        return convertView;
    }

    @Override
    public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        List<Cart.DataBean.ListBean> list = dataBeanList.get(groupPosition).getList();
        Cart.DataBean.ListBean listBean = list.get(childPosition);
        ViewHolder2 holder2;
        if (convertView ==null){
            convertView = View.inflate(parent.getContext(),R.layout.cart_recy_two,null);
            holder2 = new ViewHolder2(convertView);
            convertView.setTag(holder2);
        }else {
            holder2 = (ViewHolder2) convertView.getTag();
        }
        //设置图片
//        Uri uri = Uri.parse(listBean.getImages());
//        holder2.sdvImage.setImageURI(uri);
        holder2.sdvImage.setImageURI(Uri.parse(ImgProcess.getImg(listBean.getImages())));

        //设置商品名
        holder2.shopname.setText(listBean.getTitle());

        //设置价格
        holder2.txtPrice.setText("¥:"+listBean.getPrice());

        //加减器
        holder2.subView.setNumber(listBean.getNum());


        //设置加减器是否选中
        holder2.shopcb.setChecked(listBean.getSelected() ==1);
        holder2.shopcb.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mOnCartListener !=null){
                    mOnCartListener.onCartShopChecked(groupPosition,childPosition);
                }
            }
        });

        //加减器通过接口回调暴露给外面
        holder2.subView.setOnNumberChangeListener(new MyAddSubView.OnNumberChangeListener() {
            @Override
            public void onNumberChange(int num) {
                if (mOnCartListener !=null){
                    mOnCartListener.onCartSubviewChecked(groupPosition,childPosition,num);
                }
            }
        });
        return convertView;
    }



    //组的数据
    public static class ViewHolder1 {

        private final CheckBox sJcb;
        private final TextView sJname;

        public ViewHolder1(View rootView){
            sJcb = rootView.findViewById(R.id.cb_sj);
            sJname = rootView.findViewById(R.id.txt_sj_name);
        }

    }
    //组的数据
    public static class ViewHolder2 {


        private final CheckBox shopcb;
        private final SimpleDraweeView sdvImage;
        private final TextView shopname;
        private final TextView txtPrice;
        private final MyAddSubView subView;

        public ViewHolder2(View rootView){
            shopcb = rootView.findViewById(R.id.cb_shop);
            sdvImage = rootView.findViewById(R.id.sdv_image);
            shopname = rootView.findViewById(R.id.txt_shopname);
            txtPrice = rootView.findViewById(R.id.txt_shopprice);
            subView = rootView.findViewById(R.id.subview);
        }

    }

    /**
     * 判断商家的商品是否选中
     * @param groupPosition
     * @return
     */
    public boolean isAllSjShopselected(int groupPosition){
        //获取商家数据
        Cart.DataBean dataBean = dataBeanList.get(groupPosition);
        //获取商品数据
        List<Cart.DataBean.ListBean> list = dataBean.getList();

        for (Cart.DataBean.ListBean listBean: list){
            //判断商品是否都选中,一个没选中商家的复选框都不选中 ==0是选中状态
            if (listBean.getSelected() ==0){
                return false;
            }
        }
        return true;
    }


    /**
     * 底部全选框的状态
     * @return
     */
    public boolean isBottomAllselected(){
        for (int i = 0; i < dataBeanList.size(); i++) {
            Cart.DataBean dataBean = dataBeanList.get(i);
            List<Cart.DataBean.ListBean> list = dataBean.getList();
            for (int j = 0; j < list.size(); j++) {
                if (list.get(j).getSelected() ==0){
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 计算商品总的数量
     * @return
     */
    public int ShopNumber(){
      int  shopnums = 0;
        for (int i = 0; i < dataBeanList.size(); i++) {
            Cart.DataBean dataBean = dataBeanList.get(i);
            List<Cart.DataBean.ListBean> list = dataBean.getList();
            for (int j = 0; j < list.size(); j++) {
                if (list.get(j).getSelected() ==1){
                    int num = list.get(j).getNum();
                    shopnums += num;
                }
            }
        }
        return shopnums;
    }


    /**
     * 计算商品的总价格
     * @return
     */
    public float ShopPrices(){
       float prices = 0;
        for (int i = 0; i < dataBeanList.size(); i++) {
            Cart.DataBean dataBean = dataBeanList.get(i);
            List<Cart.DataBean.ListBean> list = dataBean.getList();
            for (int j = 0; j < list.size(); j++) {
                if (list.get(j).getSelected() == 1){
                    int price = list.get(j).getPrice();
                    int num = list.get(j).getNum();
                    prices += price * num;

                }
            }
        }
        return prices;
    }


    /**
     * 商家选中时商品都选中
     * @param groupPosition
     * @param isSelected
     */
    public void SjSelected(int groupPosition, boolean isSelected){
        Cart.DataBean dataBean = dataBeanList.get(groupPosition);
        List<Cart.DataBean.ListBean> list = dataBean.getList();
        for (int i = 0; i < list.size(); i++) {
            Cart.DataBean.ListBean listBean = list.get(i);
            listBean.setSelected(isSelected ? 1 : 0);
        }
    }

    /**
     * 当商品都选中时更新商家的状态
     * @param groupPosition
     * @param childPosition
     */
    public void ShopSelected(int groupPosition,int childPosition){
        Cart.DataBean dataBean = dataBeanList.get(groupPosition);
        List<Cart.DataBean.ListBean> list = dataBean.getList();
        Cart.DataBean.ListBean listBean = list.get(childPosition);
        listBean.setSelected(listBean.getSelected() ==0 ? 1 : 0);
    }

    /**
     * 底部全选框状态选中时更新以上所有商品状态
     * @param selected
     */
    public void ButtomSelected(boolean selected){
        for (int i = 0; i < dataBeanList.size(); i++) {
            Cart.DataBean dataBean = dataBeanList.get(i);
            List<Cart.DataBean.ListBean> list = dataBean.getList();
            for (int j = 0; j < list.size(); j++) {
                list.get(j).setSelected(selected ? 1 : 0);
            }
        }
    }

    /**
     * 当商品加减器被点击时改变里面商品的数量
     * @param groupPosition
     * @param childPosition
     * @param number
     */
    public void subviewSelected(int groupPosition, int childPosition , int number){
        Cart.DataBean dataBean = dataBeanList.get(groupPosition);
        List<Cart.DataBean.ListBean> list = dataBean.getList();
        Cart.DataBean.ListBean listBean = list.get(childPosition);
        listBean.setNum(number);
    }


    /**
     * 接口回调
     */
    public interface OnCartListener{
        /**
         * 点击商家复选框的时候调用
         * @param groupPosition
         */
        void onCartSjChecked(int groupPosition);

        /**
         * 点击商品复选框的时候调用
         * @param groupPosition
         * @param childPosition
         */
        void onCartShopChecked(int groupPosition,int childPosition);

        /**
         * 点击购物车加减器的时候调用
         * @param groupPosition
         * @param childPosition
         * @param number
         */
        void onCartSubviewChecked(int groupPosition,int childPosition,int number);
    }


    public OnCartListener mOnCartListener;

    /**
     * 给商家商品加减器设置监听
     * @param onCartListener
     */
    public void setOnCartListener(OnCartListener onCartListener){
        mOnCartListener = onCartListener;
    }


////////////////////////////////////////////////////////下面的东西不用写//////////////////////////////////////////////
    @Override
    public Object getGroup(int groupPosition) {
        return null;
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return null;
    }

    @Override
    public long getGroupId(int groupPosition) {
        return 0;
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return 0;
    }

    @Override
    public boolean hasStableIds() {
        return false;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return false;
    }
}

12:开始写主页面了

1:布局使用ExpandableListView控件展示商品列表
在这里插入图片描述

<ExpandableListView
        android:id="@+id/cart_recy"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="9"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center"
        android:paddingLeft="10dp"
        android:orientation="horizontal">
        <CheckBox
            android:id="@+id/all_cb"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:text="全选"/>
        <TextView
            android:id="@+id/txt_price"
            android:layout_width="0dp"
            android:layout_weight="2"
            android:padding="10dp"
            android:layout_height="wrap_content" />
        <Button
            android:id="@+id/btn_jiesuan"
            android:layout_width="0dp"
            android:layout_weight="2"
            android:layout_height="wrap_content"
            android:background="#ea6363"
            android:textColor="#fff"
            android:text="去结算"/>
    </LinearLayout>

2:actvit中的主代码

public class MainActivity extends AppCompatActivity implements CartView, View.OnClickListener {

    private ExpandableListView cart_recy;
    private CheckBox all_cb;
    private TextView txt_price;
    private CartPresenter presenter;
    private CartAdapter cartAdapter;
    private Button btn_jiesuan;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
    }

    private void initData() {
        presenter = new CartPresenter(this);
        presenter.showCart();
    }


    private void initView() {
        cart_recy = (ExpandableListView) findViewById(R.id.cart_recy);
        all_cb = (CheckBox) findViewById(R.id.all_cb);
        txt_price = (TextView) findViewById(R.id.txt_price);
        btn_jiesuan = (Button) findViewById(R.id.btn_jiesuan);
        btn_jiesuan.setOnClickListener(this);
        all_cb.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_jiesuan:

                break;
            case R.id.all_cb:
                boolean bottomAllselected = cartAdapter.isBottomAllselected();
                cartAdapter.ButtomSelected(!bottomAllselected);
                cartAdapter.notifyDataSetChanged();
                notifyButtomNumber();
                break;
        }
    }

    @Override
    public void getCart(Cart cart) {
        List<Cart.DataBean> data = cart.getData();
        cartAdapter = new CartAdapter(data);
        cartAdapter.setOnCartListener(new CartAdapter.OnCartListener() {
            @Override
            public void onCartSjChecked(int groupPosition) {
                /**
                 * 点击商家的时候回调
                 */
                boolean allSjShopselected = cartAdapter.isAllSjShopselected(groupPosition);
                cartAdapter.SjSelected(groupPosition, !allSjShopselected);
                cartAdapter.notifyDataSetChanged();
                notifyButtomNumber();
            }

            @Override
            public void onCartShopChecked(int groupPosition, int childPosition) {
                /**
                 * 点击商品的时候回调
                 */
                cartAdapter.ShopSelected(groupPosition, childPosition);
                cartAdapter.notifyDataSetChanged();
                notifyButtomNumber();
            }

            @Override
            public void onCartSubviewChecked(int groupPosition, int childPosition, int number) {
                /**
                 * 加减器回调
                 */
                cartAdapter.subviewSelected(groupPosition, childPosition, number);
                cartAdapter.notifyDataSetChanged();
                notifyButtomNumber();
            }
        });
        cart_recy.setAdapter(cartAdapter);

        // 展开二级列表
        for (int x = 0; x < data.size(); x++) {
            cart_recy.expandGroup(x);
        }
    }

    @Override
    public void faild(Exception e) {
        Toast.makeText(this, "获取数据失败", Toast.LENGTH_SHORT).show();
    }

    private void notifyButtomNumber() {
        //去判断是否所有的商品都被选中
        boolean bottomAllselected = cartAdapter.isBottomAllselected();
        all_cb.setChecked(bottomAllselected);
        //计算总计
        float prices = cartAdapter.ShopPrices();
        txt_price.setText("总计" + prices);

        int number = cartAdapter.ShopNumber();
        btn_jiesuan.setText("去结算("+number+")");
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_43117800/article/details/85125340
今日推荐