商城项目实战 | 14.1 仿京东购物车的实现(一)

本文为菜鸟窝作者刘婷的连载。”商城项目实战”系列来聊聊仿”京东淘宝的购物商城”如何实现。

商城项目之前已经完成了主页、分类以及热门三大模块了,下面就是购物车了,商城项目中的购物车模块是仿照京东商城而来的,在实现之前都要来看看效果图。

效果图
效果图

在上一篇文章《商城项目实战 | 13.1 Android 数据存储之 SharedPreferences 的存储方式和安全性》最后的结束语中也说过了,购物车模块中的商品数据因为是用户暂时存储的商品、加上一般购物车中的商品不会太多,也没必要上传到网络服务器中去,所以在后面的购物车的商品数据存储我们也将使用 SharedPreferences 的存储方式。那么我们先来实现购物车中的商品数据存储。

实现购物车商品数据存储

购物车的商品数据既然要使用 SharedPreferences 来存储,那么我们首先就要写一个专门存放 SharedPreferences 相关操作的工具类,用来对数据的读写处理。

1. 实现 SharedPreferences 工具类

新建文件 SharedPreferencesUtils,用于数据的读写操作,后期对于商品数据的操作可以直接调用该 class 中的方法,SharedPreferences 对于数据的操作非常简单,我这里就展示下 int 类型数据的读写。

public static boolean putInt(Context context, String key, int value) {
        SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor.putInt(key, value);
        return editor.commit();
    }

    public static int getInt(Context context, String key) {
        return getInt(context, key, -1);
    }

    public static int getInt(Context context, String key, int defaultValue) {
        SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
        return settings.getInt(key, defaultValue);
    }

SharedPreferences 的具体使用也可以参考文章《商城项目实战 | 13.1 Android 数据存储之 SharedPreferences 的存储方式和安全性》。

2. 实现购物车数据存储工具类

实现购物车数据存储工具类主要是要实现对于 json 格式数据的转化处理以及对数据的增删改查操作。

2.1 转化数据类型

新建 CartProvider class 文件,用于专门针对购物车中数据的操作,因为使用的数据都是 json 格式的数据,所以在存储的过程中需要一定的转化,例如将 ShoppingCartInfo 对象的 list 列表转化为 SparseArray 类型的 datas,其中 ShoppingCartInfo 实体类就是购物车信息类,包括 count 数量和 isChecked 是否被选中两个属性。

private void listToSparse(){

        List<ShoppingCartInfo> carts =  getDataFromLocal();

        if(carts!=null && carts.size()>0){

            for (ShoppingCartInfo cart:
                    carts) {

                datas.put(cart.getId().intValue(),cart);
            }
        }

    }

    public  List<ShoppingCartInfo> getDataFromLocal(){

        String json = SharedPreferencesUtils.getString(mContext,CART_JSON);
        List<ShoppingCartInfo> carts =null;
        if(json !=null ){

            carts = JsonUtils.fromJson(json,new TypeToken<List<ShoppingCartInfo>>(){}.getType());

        }

        return  carts;

    }

其中的 getDataFromLocal() 方法是用于获取本地数据,也将 json 格式的数据转化为了 List 列表,这里需要第三方 json 数据处理的开源框架 Gson ,因此在 build.gradle 中不要忘记了添加 Gson 的依赖。

2.2 实现对数据的增删改查

之前已经写好了 SharedPreferencesUtils 文件的话,那么对于购物车中商品数据的增删改查就很简单了,直接调用里面的方法就好了。比如需要增加数据的时候。

public void put(ShoppingCartInfo cart){

        ShoppingCartInfo temp =  datas.get(cart.getId().intValue());

        if(temp !=null){
            temp.setCount(temp.getCount()+1);
        }
        else{
            temp = cart;
            temp.setCount(1);
        }

        datas.put(cart.getId().intValue(),temp);

        commit();

    }

    public void commit(){

        List<ShoppingCartInfo> carts = sparseToList();

        SharedPreferencesUtils.putString(mContext,CART_JSON,JsonUtils.toJSON(carts));

    }

增加数据的时候,就是要将 datas 中的数据都读取出来,然后进行数据类型转化,最后在 commit() 方法中直接调用了 SharedPreferencesUtils 中的 putString() 方法,本地存储数据。

而删除数据的处理也很类似,只要 调用 SparseArray.delete() 方法,修改数据则是直接调用 SparseArray.put() 方法,当然无论是增删改中的哪种,最后都要调用 commit() 方法,对内存中的数据进行操作。

至于数据的查询,之前就已经写好了,直接调用 getDataFromLocal() 方法。

public List<ShoppingCartInfo> getAll(){
        return  getDataFromLocal();
    }

这就获取到了本地存储的所有数据了,也就是查询数据的操作。

实现在热门中添加商品到购物车

先看下热门模块的界面。

效果图
效果图

热门商品列表模块的实现请参考文章《商城项目实战 | 8.2 SwipeRefreshLayout 实现可以下拉刷新和加载更多的热门商品列表》,这里的商品列表的每一项中都有一个立即购买的按钮,我们就实现点击立即购买按钮,将商品添加到购物车商品列表中。

要将商品添加到购物车商品列表中就是要为购物车商品列表添加数据,那么就要使用之前写好的 CartProvider 中的 put(ShoppingCartInfo cart) 方法,因为是对列表 item 项中按钮的操作,所以就要修改下热门商品的 Adapter ,也就是 HWAdapter。修改如下,先声明 CartProvider 。

private CartProvider provider ;

之后在 Adapter 的构造方法中创建好 CartProvider。

provider = new CartProvider(context);

为立即购买按钮添加点击事件监听。

Button button =viewHolder.getButton(R.id.btn_add);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                provider.put(convertData(wares));
                ToastUtils.show(context,context.getString(R.string.added_to_cart));
            }
        });

convertData(WaresInfo item) 方法就是 new 一个 ShoppingCartInfo 对象,上面的代码就是点击立即购买后,将该 item 项目中的商品数据添加到本地存储中,同时提示加入购物车成功。

显示购物车商品

已经添加商品到购物车中,那么在购物车中也要将商品显示出来。

1. 定义商品列表 item 布局

对于列表的实现,首先就是要写好列表 item 项的布局。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/selector_list_item"
    android:padding="5dp"
    android:gravity="center_vertical"
    >

    <CheckBox
        android:id="@+id/cart_checkbox_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusable="false"
        android:clickable="false"
        style="@style/cart_check_box_style"
        android:layout_gravity="center"/>


    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        >

        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/cart_drawee_view"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_gravity="center"
            />


        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            >


            <TextView
                android:id="@+id/cart_tv_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="20dp"
                android:textColor="@color/gray"
                android:textSize="14sp"
                android:maxLines="2"
                />

            <TextView
                android:id="@+id/cart_tv_price"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="16sp"
                android:textColor="@color/crimson"
                android:layout_gravity="right"
                />

            <com.liuting.cniao_shop.widget.AddSubNumberLayout
                android:id="@+id/cart_layout_number"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                app:value="1"
                app:minValue="1"
                app:variation="1"
                app:maxValue="10"
                app:btnAddBackground="@android:color/white"
                app:btnSubBackground="@android:color/white"
                app:textViewBackground="@android:color/white"
                app:textViewTextSize="16sp"
                app:btnSubTextSize="22sp"
                app:btnAddTextSize="22sp"
                />

        </LinearLayout>
    </LinearLayout>
</LinearLayout>

布局中有 checkbox 选择按钮、商品图片、商品名称、价格以及数字加减控件。

2. 定义商品列表 Adapter

Adapter 的实现很简单了,新建 CartAdapter,代码如下。

public class CartAdapter extends SimpleAdapter<ShoppingCartInfo> {

    public CartAdapter(Context context, List<ShoppingCartInfo> datas, final CheckBox checkBox, TextView tv) {
        super(context, R.layout.recycler_item_cart_layout, datas);
    }


    @Override
    protected void convert(BaseViewHolder viewHoder, final ShoppingCartInfo item) {

        viewHoder.getTextView(R.id.cart_tv_title).setText(item.getName());
        viewHoder.getTextView(R.id.cart_tv_price).setText("¥"+item.getPrice());
        SimpleDraweeView draweeView = (SimpleDraweeView) viewHoder.getView(R.id.cart_drawee_view);
        draweeView.setImageURI(Uri.parse(item.getImgUrl()));

        CheckBox checkBox = (CheckBox) viewHoder.getView(R.id.cart_checkbox_item);
        checkBox.setChecked(item.isChecked());


        AddSubNumberLayout numberAddSubView = (AddSubNumberLayout) viewHoder.getView(R.id.cart_layout_number);

        numberAddSubView.setValue(item.getCount());
    }

}

在 Adapter 中添加布局文件,然后声明初始化好控件。

3. 实现购物车布局

购物车界面的布局根据上文中的效果图,需要一个商品列表、全选按钮、合计价格以及结算按钮。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/cart_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        >

    </android.support.v7.widget.RecyclerView>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:paddingTop="10dp"
        android:paddingBottom="10dp"
        android:paddingLeft="5dp"
        android:paddingRight="5dp"
        android:background="#802f4f4f"
        android:gravity="center_vertical"
        >

        <CheckBox
            android:id="@+id/cart_checkbox_all"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:checked="true"
            android:text="@string/check_all"
            style="@style/cart_check_box_style"/>


        <TextView
            android:id="@+id/cart_tv_total"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@+id/cart_checkbox_all"
            android:layout_marginLeft="@dimen/large_margin"
            android:layout_centerVertical="true"
            android:textSize="16sp"
            android:text="@string/sum"/>

        <Button
            android:id="@+id/cart_btn_order"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:minHeight="40dp"
            android:minWidth="80dp"
            android:text="@string/go_to_buy"
            style="@style/bigRedButton"/>

    </RelativeLayout>
</LinearLayout>

布局文件的实现基本上都很简单,没有什么复杂的控件。

4. 实现商品列表显示

布局都画好了,下面就是为 RecyclerView 添加 Adapter,设置相关属性就好了。

private void showData(){
        List<ShoppingCartInfo> carts = cartProvider.getAll();

        mAdapter = new CartAdapter(getContext(),carts,mCheckBox,mTextTotal);

        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        mRecyclerView.addItemDecoration(new WareItemDecoration(getContext(),WareItemDecoration.VERTICAL_LIST));

    }

RecyclerView 的相关属性配置好了,就算完成了商品列表的显示,下面看效果。

效果图

运行代码获取效果图。

效果图
效果图

这是目前实现的效果,已经基本实现了购物车模块的商品显示了,但是商品的选择、合计的计算以及编辑状态的实现等都还没有写好,在下篇文章中会继续详细说明实现的方法和过程。

《Android群英传》作者带你解锁设计布局的新姿势 http://mp.weixin.qq.com/s/k7gCBJpiXK0g8Ed2FVHQ3A

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容