我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android App开发实战项目之购物车(附源码 超详细必看)

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android App开发实战项目之购物车(附源码 超详细必看)

需要源码请点赞关注收藏后评论区留言~~~

一、需求描述

电商App的购物车可谓是司空见惯了,可以知道购物车除了底部有一个结算行,其余部分主要是已加入购物车的商品列表,然后每个商品左边是商品小图,右边是商品名称以及价格,第一次进入购物车页面应该是空的,随着加入东西的增加而增加。并且在其他界面也能看到购物车,比如有新商品加入时数字会加一

二、界面设计

主要用到了以下控件

线性布局

网格布局

相对布局

数据库SQLite

全局内存

存储卡文件

共享参数SharedPreferences

 效果如下

 

三、关键部分

1:关于页面跳转

因为购物车页面允许直接跳到商场页面,并且商场页面也允许跳到购物车页面,所以如果用户在这两个页面之间来回跳转,然后再按返回键,结果发现返回的时候也是在这两个页面之间跳转,出现问题的原因在于:每次启动活动页面都往活动栈中加入一个新活动,那么返回出栈之时,也只好一个个活动依次退出了

2:关于商品图片的缓存

通常商品图片由后端服务器提供,App打开页面时再从服务器下载所需的商品图,可是购物车模块的多个页面都会展示商品图片,如果每次都到服务器请求图片,显然非常消耗时间和流浪,因此App都会缓存常用的图片,一旦从服务器成功下载图片,便在手机储存卡上保存图片文件。然后下次界面需要加载商品图片时,就先从存储卡寻找该图片,如果找到就读取,没找到再去服务器下载

四、部分源码

ShoppingDetailActivity

package com.example.chapter06;import android.annotation.SuppressLint;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.ImageView;import android.widget.TextView;import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;import com.example.chapter06.bean.GoodsInfo;import com.example.chapter06.database.CartDBHelper;import com.example.chapter06.database.GoodsDBHelper;import com.example.chapter06.util.ToastUtil;@SuppressLint("SetTextI18n")public class ShoppingDetailActivity extends AppCompatActivity implements View.OnClickListener {    private TextView tv_title;    private TextView tv_count;    private TextView tv_goods_price;    private TextView tv_goods_desc;    private ImageView iv_goods_pic;    private long mGoodsId; // 当前商品的商品编号    private GoodsDBHelper mGoodsHelper; // 声明一个商品数据库的帮助器对象    private CartDBHelper mCartHelper; // 声明一个购物车数据库的帮助器对象    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_shopping_detail);        tv_title = findViewById(R.id.tv_title);        tv_count = findViewById(R.id.tv_count);        tv_goods_price = findViewById(R.id.tv_goods_price);        tv_goods_desc = findViewById(R.id.tv_goods_desc);        iv_goods_pic = findViewById(R.id.iv_goods_pic);        findViewById(R.id.iv_back).setOnClickListener(this);        findViewById(R.id.iv_cart).setOnClickListener(this);        findViewById(R.id.btn_add_cart).setOnClickListener(this);        tv_count.setText("" + MainApplication.goodsCount);    }    @Override    public void onClick(View v) {        if (v.getId() == R.id.iv_back) { // 点击了返回图标            finish(); // 关闭当前页面        } else if (v.getId() == R.id.iv_cart) { // 点击了购物车图标            Intent intent = new Intent(this, ShoppingCartActivity.class);            startActivity(intent); // 跳转到购物车页面        } else if (v.getId() == R.id.btn_add_cart) { // 点击了“添加”按钮            addToCart(mGoodsId); // 把该商品添加到购物车        }    }    // 把指定编号的商品添加到购物车    private void addToCart(long goods_id) {        MainApplication.goodsCount++;        tv_count.setText("" + MainApplication.goodsCount);        mCartHelper.save(goods_id); // 把该商品填入购物车数据库        ToastUtil.show(this, "成功添加至购物车");    }    @Override    protected void onResume() {        super.onResume();        // 获取商品数据库的帮助器对象        mGoodsHelper = GoodsDBHelper.getInstance(this, 1);        mGoodsHelper.openReadLink(); // 打开商品数据库的读连接        // 获取购物车数据库的帮助器对象        mCartHelper = CartDBHelper.getInstance(this, 1);        mCartHelper.openWriteLink(); // 打开购物车数据库的写连接        showDetail(); // 展示商品详情    }    @Override    protected void onPause() {        super.onPause();        mGoodsHelper.closeLink(); // 关闭商品数据库的数据库连接        mCartHelper.closeLink(); // 关闭购物车数据库的数据库连接    }    private void showDetail() {        // 获取上一个页面传来的商品编号        mGoodsId = getIntent().getLongExtra("goods_id", 0L);        if (mGoodsId > 0) {            // 根据商品编号查询商品数据库中的商品记录            GoodsInfo info = mGoodsHelper.queryById(mGoodsId);            tv_title.setText(info.name); // 设置商品名称            tv_goods_desc.setText(info.desc); // 设置商品描述            tv_goods_price.setText("" + (int)info.price); // 设置商品价格            iv_goods_pic.setImageURI(Uri.parse(info.pic_path)); // 设置商品图片        }    }}

ShoppingChannelActivity类

package com.example.chapter06;import android.annotation.SuppressLint;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.widget.Button;import android.widget.GridLayout;import android.widget.ImageView;import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;import com.example.chapter06.bean.GoodsInfo;import com.example.chapter06.database.CartDBHelper;import com.example.chapter06.database.GoodsDBHelper;import com.example.chapter06.util.ToastUtil;import java.util.ArrayList;import java.util.List;@SuppressLint("SetTextI18n")public class ShoppingChannelActivity extends AppCompatActivity implements View.OnClickListener {    private TextView tv_count;    private GridLayout gl_channel; // 声明一个商品频道的网格布局对象    private GoodsDBHelper mGoodsHelper; // 声明一个商品数据库的帮助器对象    private CartDBHelper mCartHelper; // 声明一个购物车数据库的帮助器对象    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_shopping_channel);        TextView tv_title = findViewById(R.id.tv_title);        tv_title.setText("手机商场");        tv_count = findViewById(R.id.tv_count);        gl_channel = findViewById(R.id.gl_channel);        findViewById(R.id.iv_back).setOnClickListener(this);        findViewById(R.id.iv_cart).setOnClickListener(this);    }    @Override    public void onClick(View v) {        if (v.getId() == R.id.iv_back) { // 点击了返回图标            finish(); // 关闭当前页面        } else if (v.getId() == R.id.iv_cart) { // 点击了购物车图标            // 从商场页面跳到购物车页面            Intent intent = new Intent(this, ShoppingCartActivity.class);            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // 设置启动标志            startActivity(intent); // 跳转到购物车页面        }    }    // 把指定编号的商品添加到购物车    private void addToCart(long goods_id, String goods_name) {        MainApplication.goodsCount++;        tv_count.setText("" + MainApplication.goodsCount);        mCartHelper.save(goods_id); // 把该商品填入购物车数据库        ToastUtil.show(this, "已添加一部" + goods_name + "到购物车");    }    @Override    protected void onResume() {        super.onResume();        tv_count.setText("" + MainApplication.goodsCount);        // 获取商品数据库的帮助器对象        mGoodsHelper = GoodsDBHelper.getInstance(this, 1);        mGoodsHelper.openReadLink(); // 打开商品数据库的读连接        // 获取购物车数据库的帮助器对象        mCartHelper = CartDBHelper.getInstance(this, 1);        mCartHelper.openWriteLink(); // 打开购物车数据库的写连接        showGoods(); // 展示商品列表    }    @Override    protected void onPause() {        super.onPause();        mGoodsHelper.closeLink(); // 关闭商品数据库的数据库连接        mCartHelper.closeLink(); // 关闭购物车数据库的数据库连接    }    private void showGoods() {        gl_channel.removeAllViews(); // 移除下面的所有子视图        // 查询商品数据库中的所有商品记录        List goodsArray = mGoodsHelper.query("1=1");        for (final GoodsInfo info : goodsArray) {            // 获取布局文件item_goods.xml的根视图            View view = LayoutInflater.from(this).inflate(R.layout.item_goods, null);            ImageView iv_thumb = view.findViewById(R.id.iv_thumb);            TextView tv_name = view.findViewById(R.id.tv_name);            TextView tv_price = view.findViewById(R.id.tv_price);            Button btn_add = view.findViewById(R.id.btn_add);            tv_name.setText(info.name); // 设置商品名称            iv_thumb.setImageURI(Uri.parse(info.pic_path)); // 设置商品图片            iv_thumb.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    Intent intent = new Intent(ShoppingChannelActivity.this, ShoppingDetailActivity.class);                    intent.putExtra("goods_id", info.rowid);                    startActivity(intent); // 跳到商品详情页面                }            });            tv_price.setText("" + (int)info.price); // 设置商品价格            btn_add.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    addToCart(info.rowid, info.name); // 添加到购物车                }            });            gl_channel.addView(view); // 把商品视图添加到网格布局        }    }}

ShoppingCartActivity类

package com.example.chapter06;import android.annotation.SuppressLint;import android.app.AlertDialog;import android.content.DialogInterface;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;import com.example.chapter06.bean.CartInfo;import com.example.chapter06.bean.GoodsInfo;import com.example.chapter06.database.CartDBHelper;import com.example.chapter06.database.GoodsDBHelper;import com.example.chapter06.util.FileUtil;import com.example.chapter06.util.SharedUtil;import com.example.chapter06.util.ToastUtil;import java.util.ArrayList;import java.util.HashMap;import java.util.List;@SuppressLint("SetTextI18n")public class ShoppingCartActivity extends AppCompatActivity implements View.OnClickListener {    private final static String TAG = "ShoppingCartActivity";    private TextView tv_count;    private TextView tv_total_price;    private LinearLayout ll_content;    private LinearLayout ll_cart; // 声明一个购物车列表的线性布局对象    private LinearLayout ll_empty;    private GoodsDBHelper mGoodsHelper; // 声明一个商品数据库的帮助器对象    private CartDBHelper mCartHelper; // 声明一个购物车数据库的帮助器对象    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_shopping_cart);        TextView tv_title = findViewById(R.id.tv_title);        tv_title.setText("购物车");        tv_count = findViewById(R.id.tv_count);        tv_total_price = findViewById(R.id.tv_total_price);        ll_content = findViewById(R.id.ll_content);        ll_cart = findViewById(R.id.ll_cart);        ll_empty = findViewById(R.id.ll_empty);        findViewById(R.id.iv_back).setOnClickListener(this);        findViewById(R.id.btn_shopping_channel).setOnClickListener(this);        findViewById(R.id.btn_clear).setOnClickListener(this);        findViewById(R.id.btn_settle).setOnClickListener(this);    }    // 显示购物车图标中的商品数量    private void showCount() {        tv_count.setText("" + MainApplication.goodsCount);        if (MainApplication.goodsCount == 0) {            ll_content.setVisibility(View.GONE);            ll_cart.removeAllViews(); // 移除下面的所有子视图            mGoodsMap.clear();            ll_empty.setVisibility(View.VISIBLE);        } else {            ll_content.setVisibility(View.VISIBLE);            ll_empty.setVisibility(View.GONE);        }    }    @Override    public void onClick(View v) {        if (v.getId() == R.id.iv_back) { // 点击了返回图标            finish(); // 关闭当前页面        } else if (v.getId() == R.id.btn_shopping_channel) { // 点击了“商场”按钮            // 从购物车页面跳到商场页面            Intent intent = new Intent(this, ShoppingChannelActivity.class);            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // 设置启动标志            startActivity(intent); // 跳转到手机商场页面        } else if (v.getId() == R.id.btn_clear) { // 点击了“清空”按钮            mCartHelper.deleteAll(); // 清空购物车数据库            MainApplication.goodsCount = 0;            showCount(); // 显示最新的商品数量            ToastUtil.show(this, "购物车已清空");        } else if (v.getId() == R.id.btn_settle) { // 点击了“结算”按钮            AlertDialog.Builder builder = new AlertDialog.Builder(this);            builder.setTitle("结算商品");            builder.setMessage("客官抱歉,支付功能尚未开通,请下次再来");            builder.setPositiveButton("我知道了", null);            builder.create().show(); // 显示提醒对话框        }    }    @Override    protected void onResume() {        super.onResume();        showCount(); // 显示购物车的商品数量        // 获取商品数据库的帮助器对象        mGoodsHelper = GoodsDBHelper.getInstance(this, 1);        mGoodsHelper.openWriteLink(); // 打开商品数据库的写连接        // 获取购物车数据库的帮助器对象        mCartHelper = CartDBHelper.getInstance(this, 1);        mCartHelper.openWriteLink(); // 打开购物车数据库的写连接        downloadGoods(); // 模拟从网络下载商品图片        showCart(); // 展示购物车中的商品列表    }    @Override    protected void onPause() {        super.onPause();        mGoodsHelper.closeLink(); // 关闭商品数据库的数据库连接        mCartHelper.closeLink(); // 关闭购物车数据库的数据库连接    }    // 声明一个购物车中的商品信息列表    private List mCartArray = new ArrayList();    // 声明一个根据商品编号查找商品信息的映射    private HashMap mGoodsMap = new HashMap();    private void deleteGoods(CartInfo info) {        MainApplication.goodsCount -= info.count;        // 从购物车的数据库中删除商品        mCartHelper.delete("goods_id=" + info.goods_id);        // 从购物车的列表中删除商品        for (int i = 0; i < mCartArray.size(); i++) {            if (info.goods_id == mCartArray.get(i).goods_id) {                mCartArray.remove(i);                break;            }        }        showCount(); // 显示最新的商品数量        ToastUtil.show(this, "已从购物车删除" + mGoodsMap.get(info.goods_id).name);        mGoodsMap.remove(info.goods_id);        refreshTotalPrice(); // 刷新购物车中所有商品的总金额    }    // 展示购物车中的商品列表    private void showCart() {        ll_cart.removeAllViews(); // 移除下面的所有子视图        mCartArray = mCartHelper.query("1=1"); // 查询购物车数据库中所有的商品记录        Log.d(TAG, "mCartArray.size()=" + mCartArray.size());        if (mCartArray == null || mCartArray.size() <= 0) {            return;        }        for (int i = 0; i < mCartArray.size(); i++) {            final CartInfo info = mCartArray.get(i);            // 根据商品编号查询商品数据库中的商品记录            final GoodsInfo goods = mGoodsHelper.queryById(info.goods_id);            Log.d(TAG, "name=" + goods.name + ",price=" + goods.price + ",desc=" + goods.desc);            mGoodsMap.put(info.goods_id, goods);            // 获取布局文件item_goods.xml的根视图            View view = LayoutInflater.from(this).inflate(R.layout.item_cart, null);            ImageView iv_thumb = view.findViewById(R.id.iv_thumb);            TextView tv_name = view.findViewById(R.id.tv_name);            TextView tv_desc = view.findViewById(R.id.tv_desc);            TextView tv_count = view.findViewById(R.id.tv_count);            TextView tv_price = view.findViewById(R.id.tv_price);            TextView tv_sum = view.findViewById(R.id.tv_sum);            // 给商品行添加点击事件。点击商品行跳到商品的详情页            view.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    Intent intent = new Intent(ShoppingCartActivity.this, ShoppingDetailActivity.class);                    intent.putExtra("goods_id", info.goods_id);                    startActivity(intent); // 跳到商品详情页面                }            });            // 给商品行添加长按事件。长按商品行就删除该商品            view.setOnLongClickListener(new View.OnLongClickListener() {                @Override                public boolean onLongClick(final View v) {                    AlertDialog.Builder builder = new AlertDialog.Builder(ShoppingCartActivity.this);                    builder.setMessage("是否从购物车删除"+goods.name+"?");                    builder.setPositiveButton("是", new DialogInterface.OnClickListener() {                        @Override                        public void onClick(DialogInterface dialog, int which) {ll_cart.removeView(v); // 移除当前视图deleteGoods(info); // 删除该商品                        }                    });                    builder.setNegativeButton("否", null);                    builder.create().show(); // 显示提醒对话框                    return true;                }            });            iv_thumb.setImageURI(Uri.parse(goods.pic_path)); // 设置商品图片            tv_name.setText(goods.name); // 设置商品名称            tv_desc.setText(goods.desc); // 设置商品描述            tv_count.setText("" + info.count); // 设置商品数量            tv_price.setText("" + (int)goods.price); // 设置商品单价            tv_sum.setText("" + (int)(info.count * goods.price)); // 设置商品总价            ll_cart.addView(view); // 往购物车列表添加该商品行        }        refreshTotalPrice(); // 重新计算购物车中的商品总金额    }    // 重新计算购物车中的商品总金额    private void refreshTotalPrice() {        int total_price = 0;        for (CartInfo info : mCartArray) {            GoodsInfo goods = mGoodsMap.get(info.goods_id);            total_price += goods.price * info.count;        }        tv_total_price.setText("" + total_price);    }    private String mFirst = "true"; // 是否首次打开    // 模拟网络数据,初始化数据库中的商品信息    private void downloadGoods() {        // 获取共享参数保存的是否首次打开参数        mFirst = SharedUtil.getIntance(this).readString("first", "true");        // 获取当前App的私有下载路径        String path = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + "/";        if (mFirst.equals("true")) { // 如果是首次打开            ArrayList goodsList = GoodsInfo.getDefaultList(); // 模拟网络图片下载            for (int i = 0; i < goodsList.size(); i++) {                GoodsInfo info = goodsList.get(i);                long rowid = mGoodsHelper.insert(info); // 往商品数据库插入一条该商品的记录                info.rowid = rowid;                Bitmap pic = BitmapFactory.decodeResource(getResources(), info.pic);                String pic_path = path + rowid + ".jpg";                FileUtil.saveImage(pic_path, pic); // 往存储卡保存商品图片                pic.recycle(); // 回收位图对象                info.pic_path = pic_path;                mGoodsHelper.update(info); // 更新商品数据库中该商品记录的图片路径            }        }        // 把是否首次打开写入共享参数        SharedUtil.getIntance(this).writeString("first", "false");    }}

XML文件如下

                                                                                                                                                                                                                    

创作不易 觉得有帮助请点赞关注收藏~~~

来源地址:https://blog.csdn.net/jiebaoshayebuhui/article/details/127738664

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android App开发实战项目之购物车(附源码 超详细必看)

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录