Mvp快速搭建商城购物车模块
代碼地址如下:
http://www.demodashi.com/demo/12834.html
前言:
說到MVP的時候其實大家都不陌生,但是涉及到實際項目中使用,還是有些無從下手。因此這里小編帶著大家一步步地如何用MVP去搭建購物車模塊。
首先還是按照慣例,用一張實現的動態圖來說明吧:
看圖其實可以看得出來咱們這塊的功能主要有:
- 單個店面的選擇
- 某個店面下對某個商品的選擇
- 對某個店面里某個商品數量的增減
- 最下面的商品全選
- 對選中的商品價格的計算
- 對選中商品進行結算(主要給服務器那邊)
實現:
說完了要實現的功能,緊接著就要去分析,咱們的MVP的架子該如何去分析呢:
首先來看M層,大家都知道M層是數據層,是操作數據的關鍵層,那咱們這塊主要有獲取商品、單個商品的增減、單個商品的選中取消、單個店的選中取消、所有商品的全選取消,V層就是顯示這層了,這里就定義了幾種情況,成功獲取到商品、顯示修改時顯示某個商品、顯示錯誤頁面、顯示空的頁面,P層就是兩個層的橋梁了
對view層進行回調顯示了。
這里畫一張結構圖,來說明MVP的特點:
從圖中大家可以看得出來,首先是定義好咋們的IMode接口,接口里面只有一個獲取所有的商品方法:
//需要傳入數據的類型,該類承擔著從網絡或本地獲取數據的部分 public interface IMode<T> {void loadList(); }緊接著就是咋們的ShopMode實現類了:
//當前每次需要回調的價格變量 private double price; private List<ShopCartBean> select_list = new ArrayList<>();//傳到結算頁面的商品數據 private List<ShopCartBean> allShopCarBean = new ArrayList<>();//傳到結算頁面的商品數據 //獲取的數據源部分,從Asset目錄下面的shopcartdata.json獲取,獲取成功后,將數據交給了回調接口,并且將獲取到的數據放到allShopCarBean集合里面 @Override public void loadList() {StringBuilder stringBuilder = new StringBuilder();try {AssetManager assetManager = context.getAssets();BufferedReader bf = new BufferedReader(new InputStreamReader(assetManager.open("shopcartdata.json")));String line;while ((line = bf.readLine()) != null) {stringBuilder.append(line);}String json = stringBuilder.toString();Gson gson = new Gson();List<ShopCartBean> list = gson.fromJson(json, new TypeToken<List<ShopCartBean>>() {}.getType());//對于不是類的情況,用這個參數給出listener.loadSuccess(list);allShopCarBean.addAll(list);} catch (Exception e) {e.printStackTrace();} } //點擊了某個店面下的某個商品的數量減少, parent_position:店面的id, child_position:商品的id public void numberReduce(int parent_position, int child_position) {ShopCartBean bean = allShopCarBean.get(parent_position);List<GoodsBean> goodsList = bean.getGoods();GoodsBean goodsBean = goodsList.get(child_position);String goods_num = goodsBean.getGoods_number();int goodsNum = Integer.parseInt(goods_num);boolean canReduce = false;if (goodsNum > 1) {canReduce = true;}//通過id獲取相應的商品GoodsBean selectGoodsBean = goodsNumChange(2, parent_position, child_position);Log.d(TAG, "goodsBean.number:" + goodsBean.getGoods_number());if (selectGoodsBean.isCheck() && canReduce) {//價格需要在前面的基礎上減去單個商品的價格,相當于數量減少了一個price -= Double.parseDouble(selectGoodsBean.getGoods_price());Log.d(TAG, "price:" + price);listener.onNumberReduce(price, select_list);} } //商品數量的增減并且返回選中的GoodsBean private GoodsBean goodsNumChange(int type, int parent_position, int child_position) {ShopCartBean bean = allShopCarBean.get(parent_position);List<GoodsBean> goodsList = bean.getGoods();GoodsBean goodsBean = goodsList.get(child_position);String goods_num = goodsBean.getGoods_number();int goodsNum = Integer.parseInt(goods_num);if (type == 1) {goodsNum = goodsNum + 1;} else {if (goodsNum > 1) {goodsNum = goodsNum - 1;}}goodsBean.setGoods_number(String.valueOf(goodsNum));ShopCartBean selectBean = new ShopCartBean();//對當前的選中的ShopCartBean進行重新給值selectBean.clearGoods(bean, select_list);//如果之前在select_list中存在,移除之前的,將新的放到該集合中int index = isContainsShopBean(select_list, selectBean);if (index != -1) {select_list.remove(index);}select_list.add(selectBean);listener.onNumberChange(parent_position);return goodsBean; } //判斷當前的shopCartBean是否在之前選中的集合中 private int isContainsShopBean(List<ShopCartBean> existShopBeanList, ShopCartBean shopCartBean) {for (int i = 0; i < existShopBeanList.size(); i++) {ShopCartBean selectBean = existShopBeanList.get(i);Log.d(TAG, "selectBean.getSupplier_id" + selectBean.getSupplier_id());Log.d(TAG, "shopCartBean.getSupplier_id" + shopCartBean.getSupplier_id());if (selectBean.getSupplier_id().equals(shopCartBean.getSupplier_id())) {return i;}}return -1; } //點擊了某一個店面,此時就是全選當前店面下的商品或是全消店面下面的商品 public void itemChildClick(int position) {ShopCartBean bean = allShopCarBean.get(position);//如果之前存在當前的ShopCartBean則進行移除操作int index = isContainsShopBean(select_list, bean);if (index != -1) {select_list.remove(index);}boolean isSelected;boolean checkAll;//選中與未選中做取反操作if (bean.isCheck()) {isSelected = false;} else {isSelected = true;}//保存店鋪點擊狀態bean.setCheck(isSelected);//通知全選CheckBox的選擇狀態,看是不是全選的if (allSelect() == allShopCarBean.size()) {checkAll = true;} else {checkAll = false;}//這里如果是選中了某一個店,需要對這個店下面的商品總價格加操作if (isSelected) {for (int i = 0; i < bean.getGoods().size(); i++) {//只有在沒選中的情況下才會去修改狀態以及總價格if (!bean.getGoods().get(i).isCheck()) {bean.getGoods().get(i).setCheck(true);price += Double.parseDouble(bean.getGoods().get(i).getGoods_number()) * Double.parseDouble(bean.getGoods().get(i).getGoods_price());}}select_list.add(bean);} else {// 解決點擊取消選擇商品時,店鋪全選按鈕取消選擇狀態,不會不變成全不選if (allChildSelect(position) == bean.getGoods().size()) {for (int i = 0; i < bean.getGoods().size(); i++) {//只有在選中情況下才會去修改狀態以及總價格if (bean.getGoods().get(i).isCheck()) {bean.getGoods().get(i).setCheck(false);price -= Double.parseDouble(bean.getGoods().get(i).getGoods_number()) * Double.parseDouble(bean.getGoods().get(i).getGoods_price());}}select_list.remove(bean);}}listener.onItemChildClick(price, checkAll, select_list, position); } //對某一個商品進行選中與未選中 public void childClick(int parent_position, int child_position) {ShopCartBean bean = allShopCarBean.get(parent_position);ShopCartBean selectBean = new ShopCartBean();selectBean.clearGoods(bean, select_list);List<GoodsBean> goodsList = bean.getGoods();GoodsBean goodsBean = goodsList.get(child_position);boolean isSelected;boolean checkAll;if (goodsBean.isCheck()) {isSelected = false;price -= Double.parseDouble(goodsBean.getGoods_number()) * Double.parseDouble(goodsBean.getGoods_price());selectBean.getGoods().remove(goodsBean);} else {isSelected = true;price += Double.parseDouble(goodsBean.getGoods_number()) * Double.parseDouble(goodsBean.getGoods_price());selectBean.getGoods().add(goodsBean);}//保存商品點擊狀態goodsBean.setCheck(isSelected);//通知店鋪選擇的狀態if (allChildSelect(parent_position) == goodsList.size()) {bean.setCheck(true);selectBean.setCheck(true);} else {bean.setCheck(false);selectBean.setCheck(false);}int index = isContainsShopBean(select_list, selectBean);if (index != -1) {select_list.remove(index);}select_list.add(selectBean);//通知全選CheckBox的選擇狀態if (allSelect() == allShopCarBean.size()) {checkAll = true;} else {checkAll = false;}listener.onItemChildClick(price, checkAll, select_list, parent_position); } //所有的店面下面所有的商品選中的操作 public void selectAll() {price = 0;select_list.clear();for (int i = 0; i < allShopCarBean.size(); i++) {ShopCartBean shopCartBean = allShopCarBean.get(i);//選擇店鋪if (!shopCartBean.isCheck()) {shopCartBean.setCheck(true);}for (int j = 0; j < shopCartBean.getGoods().size(); j++) {//選擇店鋪的商品if (!shopCartBean.getGoods().get(j).isCheck()) {shopCartBean.getGoods().get(j).setCheck(true);Log.d(TAG, "數量:" + shopCartBean.getGoods().get(j).getGoods_number());}price += Double.parseDouble(shopCartBean.getGoods().get(j).getGoods_number()) * Double.parseDouble(shopCartBean.getGoods().get(j).getGoods_price());}select_list.add(shopCartBean);}listener.onSelctAll(price, select_list); } //取消全選的操作 public void unSelectAll() {if (allSelect() == allShopCarBean.size()) {for (int i = 0; i < allShopCarBean.size(); i++) {ShopCartBean shopCartBean = allShopCarBean.get(i);if (shopCartBean.isCheck()) {shopCartBean.setCheck(false);}for (int j = 0; j < shopCartBean.getGoods().size(); j++) {if (shopCartBean.getGoods().get(j).isCheck()) {shopCartBean.getGoods().get(j).setCheck(false);}}}select_list.clear();price = 0;listener.onUnSelectAll(price, select_list);} } //某個店面下,某個商品數量加的操作 public void numberAdd(int parent_position, int child_position) {GoodsBean goodsBean = goodsNumChange(1, parent_position, child_position);if (goodsBean.isCheck()) {price += Double.parseDouble(goodsBean.getGoods_price());listener.onNumberAdd(price, select_list);} }關于mode層的業務邏輯就是這么多了,下面就是搭建p層了,看下p層的接口:
public interface Presenter {public void presenterList();}這里就定義了一個方法,主要是去看下它的子類:
public class ShopCarPresenter implements IPresenter, ShopLoaderListener {//持有view層的接口,需要v層傳進來IView view;//持有mode層的接口,此處在該類直接生成Mode mode;public ShopCarPresenter(Context context, IView view) {this.view = view;this.mode = new ShopMode(context, this);} }其實對于p層有兩種操作,一種是不對view層進行回調的操作,一種是需要對view層進行回調,由于這里分兩種情況,因此這里就舉例說明:
//看到沒就是這么簡單的一句,不帶回調到view層的 @Override public void presenterList() {mode.loadList(); } //也是一句,調用了ShopCartFragment的方法 @Override public void onNumberAdd(double price, List<ShopCartBean> select_list) {if (view instanceof ShopCartFragment) {((ShopCartFragment) view).numberAdd(price, select_list);} }總的來說,p層是我們最簡單的一層,因為它只是建立view層和mode層的橋梁,持有他們的實例。
下面再來看看view層的定義,看下接口:
public interface IView<T> {public void showSuccessPage(List<T> list);public void showSuccessPage(T t);public void showErrorPage();public void showEmptyPage(); }這里方法就根據自己業務寫方法了,其實我這里也是沒必要定義那么多方法的,真正用到了就上面兩個方法。
咋們這里view層的實例就是ShopCartFragment了,咋們可以看看它的定義:
其實就是對Iview實現,然后在不同的實現方法里面處理view,所以在view的實現類里面不會出現處理業務的代碼,只會跟view相關的代碼。
代碼補充說明:
項目代碼比較多,這個是沒辦法全部貼出來,以上是模型的實現代碼,具體的代碼結構,見 項目結構圖,以及具體的項目代碼包
項目結構圖:
Mvp快速搭建商城購物車模塊
代碼地址如下:
http://www.demodashi.com/demo/12834.html
注:本文著作權歸作者,由demo大師代發,拒絕轉載,轉載需要作者授權
總結
以上是生活随笔為你收集整理的Mvp快速搭建商城购物车模块的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一个nuxt(vue)+mongoose
- 下一篇: MAC快捷键对照表