今天我们要用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);
}
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