前言

上一篇博客主要介绍了本次网上商城的实现过程中的一些用法,这篇博客主要就是说明每个功能模式的实现方法

Android学习之网上商城(上)
Android学习之网上商城(下)

源码下载:

链接:https://pan.baidu.com/s/1Z17xBHV9iq70LwdgXxwDIQ
提取码:Lin2

Android学习之网上商城源代码

本博客内容原创,创作不易,转载请注明

本文链接

个人博客:https://ronglin.fun/?p=120
PDF链接:见博客网站
CSDN: https://blog.csdn.net/RongLin02/article/details/121876819

开发环境:

  • Android Studio版本:(Android Studio Arctic Fox 2020.3.1 Patch 3)
  • SDK版本:(Android 7.0 API24 Revision 2)
  • Gradle版本:(7.0.2)
  • Android Gradle Plugin版本:(7.0.3)

文件布局如下:

数据结构

Goods

对于每一个商品类,提供以下的成员变量

    private ArrayList<Bitmap> bitmaps;private String goodsName;private String describe;private ArrayList<String> tags;private int price;public static ArrayList<Goods> GOODSLIST =new ArrayList<>();public static Goods DEULT_GOODS = new Goods();

简单介绍一下,price变量是一个以分为单位的数,比如10000就是100.00元,这样就不会涉及到浮点数的精度问题,bitmaps是一个图片的合集,用来保存商品的一些预览图,其他就见名知意了。然后DEULT_GOODS默认商品类就是一个有内存但是没有数据的类

构造方法如下:

    public Goods(){this.bitmaps = new ArrayList<>();this.goodsName = "";this.describe = "";this.tags = new ArrayList<>();this.price = -1;}public Goods(String goodsName, String describe, String[] tags, int price){...}

除了成员变量的getter方法和setter方法还有以下方法:

public boolean equals(Goods goods){return this.getGoodsName().equals(goods.getGoodsName())&& this.getTags().equals(goods.getTags())&& this.getDescribe().equals(goods.getDescribe())&& this.getPrice() == goods.getPrice();}public static String toPriceString(int price){StringBuffer sb = new StringBuffer(String.valueOf(price));//小于2位数if (sb.length()<=2){if (sb.length() == 0){sb.insert(0,"0.00");} else if(sb.length() == 1){sb.insert(0,"0.0");} else if(sb.length() == 2){sb.insert(0,"0.");}} else {sb.insert(sb.length()-2,'.');}return sb.toString();}public static void getDefaultGoodsList(Context context)

equals方法就是判断两个Goods是否相等.
toPriceString是因为price是以分为单位的数据,要把它变成以元为单位的,例如:
10000 -> 100.00;
0 -> 0.00;
10 -> 0.10;
getDefaultGoodsList就是用来初始化商品列表的

Person

person类是一个封装用户信息的一个类
成员变量如下:

    private String id;private int num;private String username;private String password;private int money =0 ;

构造方法如下

public Person(String name, String password){this.username = name;this.password = password;}

需要注意的是,这个类中并没有对person的id和num进行初始化,所以说当要插入数据库时,要先在数据库中获取id和num值,对于这两个值的意义在数据库设计中会有说明.
除了成员变量的getter方法和setter方法还有以下方法:

    public String toString(){String t;t ="{id:%s,num:%s,username:%s,password:%s,money:%s}";t =String.format(t,this.id,this.num,this.username,this.password,this.money);return t;}

主要就是将一个person的数据输出

数据库

表格设计

数据库的设计是核心,因为采用本地数据存储,所有数据要保存在本地数据库中,接下来简单说明一下本次数据库设计
本次数据库一共新建了两个表格,如下

sqLiteDatabase.execSQL("create table person(id varchar(10) primary key,num integer,username varchar(30),password  varchar(30),money integer)");
sqLiteDatabase.execSQL("create table shopping(id varchar(10),goodsName varchar(30),time bigint)");

第一个表格是person表,元组有id(主键),num、username、password,四个,id和num是一样的,但是数据类型不一样,主要是为了区分用户名相同的用户,num表示当前第多少个用户,例如是第一个注册的,那么id = num =1,第二个注册的就是id = num =2,以此类推。
第二个表格是shopping表,用来保存用户的历史订单的,元组有id、goodsName、time,其中id就是person表格中的id,goodsName是商品名称,time则是用户购买商品的时间戳,采用的是java的时间戳格式,是一个long类型的相对于1970年开始的毫秒值。因为一个用户可能购买多个同一商品,所以说要加一个time用来区分。

代码设计

主要设计了以下方法

public class Database {private MySQLiteHelper mySQLiteHelper;private SQLiteDatabase database;public Database(MySQLiteHelper mySQLiteHelper){this.mySQLiteHelper = mySQLiteHelper;}//将person插入数据库public void insertPersonToSQLite(Person person){...}//获取当前数据库中的最大Numpublic int getPersonMaxNumFromSQLite(){...}//根据id更新数据public int updatePersonToSQLite(Person person){...}//删除personpublic int deletePersonToSQLite(Person person){...}//此方法用来查询数据库中是否存在person//优先查询id,id==null,查询username//password为空时返回第一个username的信息 不为空时匹配用户名和密码//当查询不到时返回nullpublic Person findPersonFromSQLite(String id,String username,String password){...}//插入购物清单public void insertGoodsToSQLite(Person person,Goods goods,long time){...}//删除购物项public int deleteGoodsToSQLite(Person person,Goods goods){...}//查person的所有购物项public ArrayList<String> findGoodsListFromSQLite(Person person){...}
}

注意要想插入person的时候,要先调用getPersonMaxNumFromSQLite方法获取MaxNum来设置person的id和num数据

注册登录

登录界面

效果如图:

这个界面主要是2个EditText和2个Button,注册按钮的监听方法就是点击后会跳转到注册的Activity,调用的是startActivityForResult();方法,因为需要注册界面把注册用户的信息返回回来,然后在onActivityResult()方法中将2个EditText的内容填好。登录按钮就是点击之后,先检查用户输入是否合理,例如:是否输入了密码等,如果没输入就提示一个Toast,如果输入合法,就在本地数据库中查询,如果不存在提示Toast,如果登录成功,则把当前的界面中的控件用setVisibility()方法隐藏,然后显示登录成功界面。

注册界面


登录界面比较简单,是一个单独的Activity,功能主要是,点击取消当前界面finish(),如果点击注册核对用户输入是否合法,合法的话,将数据插入数据库,插入之前要先检测一下是否在数据库中存在当前用户,标准是用户名和密码同时对应,如果存在提示一个Toast,不存在则插入数据库,然后将数据通过setResult()方法传回MainActivity

登录成功界面


登录成功界面是和登录界面同时存在的,一开始是隐藏起来的一个线性布局,等登录成功之后,从数据库中获取用户的余额和历史清单,然后将数据显示出来,也是比较简单。
因为数据库中存储的是货物的名称,当获取名称之后,还要通过当前的货物List查询出来每一个货物,将String类型的数据转化为Goods类型。
充值按钮就是增加100元给当前账户,同时更新到数据库中,注销就是退出当前账户.但是实际上并没有退出,而是把当前界面隐藏然后显示登录界面.
然后购物清单就是一个从数据库中获取数据的一个ListView

商品展示


这是商品展示界面,布局主要是一个顶部栏和一个ListVeiw.还有响应点击会弹出一个有关商品的详细信息的对话框

顶部栏

顶部栏其中有三个控件,从左到右分别是 用户 搜索框 购物车,点击用户按钮则跳转到个人中心的Fragment,用法如下:

Navigation.findNavController(GoodsFragment.this.getView()).navigate(R.id.navigation_person);

搜索框实现了一个实时查询的功能,用到了TextWatcher类,关于这个类的用法在前边有详细说明,当用户输入一个字符之后就开始搜索,搜索范围为一个商品的字符成员变量,Tag goodsName,describe代码如下:

    @Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {String search = s.toString().trim();if(search.isEmpty()){goodsViewModel.setListGoods(list);} else {resultList.clear();for (Goods t:list) {if(t.getGoodsName().contains(search)){resultList.add(t);} else if (t.getTags().toString().contains(search)){resultList.add(t);} else if (t.getDescribe().contains(search)){resultList.add(t);}}goodsViewModel.setListGoods(resultList);}}

ListView

listView中的重点就是adapter类的书写,在前面有了详细说明

public class GoodsListAdapter extends BaseAdapter

同时有关点击每一个item弹出对话框也是在这个类里调用setOnClickListener方法实现.
还有点击"+“将当前货物添加到购物车中也是在GoodsListAdapter类中实现
同时还有一个延迟效果,点击”+“之后图标变成 “√” 然后经过1s之后变回”+",在这一秒内用户无法添加货物到购物车,这延迟的实现方法用的是前面介绍的 单线程实现定时器

商品详细对话框


样式如上
一个自定义的对话框,代码框架如下

public class GoodsDialog extends Dialog implements View.OnClickListener {private Goods goods;private Context context;private DialogGoodsBinding binding;public GoodsDialog(@NonNull Context context, Goods goods) {super(context);this.goods = goods;this.context = context;}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);binding = DialogGoodsBinding.inflate(LayoutInflater.from(context));setContentView(binding.getRoot());//......}@Overridepublic void onClick(View view) {hide();}
}

就一个主要的数据就是一个Goods类,然后就是实现,点击任何地方隐藏当前对话框

购物车

主要界面如下

主要是设计为ListView加一个底边栏

ListView

关于这个ListView的BaseAdapter类,我是这样定义的

    public class ShoppingListAdapter extends BaseAdapter {private ArrayList<Goods> list_goods ;private static ArrayList<Integer> list_select = new ArrayList<>();private int allPrice = 0;private final Context context;private FragmentShoppingBinding binding;public ShoppingListAdapter(ArrayList<Goods> list, Context context, FragmentShoppingBinding binding){this.list_goods = list;this.context = context;this.binding = binding;}//......
}

这个listView有一个难点就是要标记选中,因此我用了两个ArrayList,一个是当前的商品列表,还有一个是选中的项目,这个选中的项目列表存储的标号index,比如上图,list_select中存储的就是[0,1]两个元素
第二个难点就是要计算出选中的项目的价格,这个是用allPrice变量维护的,然后当list_select变换的时候,就更新一些爱,然后通过传进来的FragmentShoppingBinding引用来显示到底边栏上

底边栏

难点是删除按钮的逻辑,我是这样设计的,现根据ShoppingListAdapter类中的list_select列表数据,将显示的list_goods中的Goods先设置成DEULT_GOODS,因为DEULT_GOODS是没有意义的,然后再用一个方法将list_goods中的所有的DEULT_GOODS删除,然后再刷新一次界面,就可以了.
删除功能的结果展示如下:

然后就是全选按钮,全选按钮中的逻辑比较简单,就是修改ShoppingListAdapter类中的list_select数据,将内容设置为全部,同时每一个item中的单选按钮根据list_select更改选中状态,即可

最后就是购买按钮,效果如下:

效果为点击购买,之后弹出一个对话框,对话框的内容为确定付款,显示用户当前所拥有的金额和购买商品所需要的金额,如果用户点击确定,则比较两个金额,用户余额不够的话提示一个Toast,够的话就在购物车中删除对应的item,然后将对应的Goods数据插入数据库中,将相应的金额扣除,更新数据库中的用户数据

总结

至此,一个简易的网上商城APP就做完了,难点在于新得框架的应用和一些功能的时间方法,还有界面设计的美观性和应对不同屏幕大小的适配.
总之,本次课设收获良多,但是无奈两周时间赶上3门考试,一边考试一边课设精力有限,界面简陋,功能简单,不过主要以学习为主.经过本次课设,对于Android开发过程有了大概的理解,获益良多,=w=

Android学习之网上商城(下)相关推荐

  1. Android学习之网上商城(上)

    前言 又到了课设的时候,这次课设比较难受,因为两周时间中还有3门考试,在课设的时候还要复习,着实耗费了不少的精力,不过也收获多多,接下来总结一下本次课设中学到的东西 Android学习之网上商城(上) ...

  2. 【Android开发】网上商城

    [Android开发]网上商城 文章目录 [Android开发]网上商城 一.开发环境需求 二.系统功能设计 三.运行结果 1. 欢迎界面 2. 搜索界面 3. 登录界面 四.主要代码 1. Home ...

  3. Django框架学习之网上商城项目一(后端设计)

    目录 一.项目需求分析 1.项目介绍 1.技术难点 2.系统功能 3.项目环境 4.后台管理页面 二.数据库模型设计 一.准备工作 二.用户认证数据库模型设计 1. app/users/models. ...

  4. Android 学习笔记之九 下拉刷新

    下拉刷新控件终结者:PullToRefreshLayout 转载请声明出处http://blog.csdn.net/zhongkejingwang/article/details/38868463 源 ...

  5. Android安卓手机网上商城系统

    程序功能说明:      使用安卓手机客户端实现的一个网络购物系统,客户端可以注册用户!登陆系统后,可以查看挑选商品,选中商品后提交到购物车,修改好购买的数量,填写好发货地址就可以提交订单了!订单提交 ...

  6. android.mk 冒号,android学习-ndk-build(androidstudio编译cocos2d-x库的cpp为so文件的解释)

    本文不作为ndk初学使用,只是对cpp等c++文件编译成so文件的过程中,参数含义,及ndk配置的解释.使用的技术比较旧. androidStudio使用gradle调用ndk-build工具编译c+ ...

  7. Android学习路线_工具篇(一)简单的编辑器

    工欲善其事,必先利其器.工具,是人类进化的一大助力,善于制造与使用工具,可以加快我们学习的速度.工具在人类的进化之路上随着人类共同进化,原始的人类需要的是原始的工具,先进的工具对于原始人来说也许是个占 ...

  8. Android课程设计--网上购物商城

    Android的特征: 提供访问硬件的API函数,简化访问过程等 具有自己的运行时和虚拟机 提供了丰富的界面控件供使用者之间调用,加快用户界面的开发速度,保证Android平台上程序界面的一致性 提供 ...

  9. android网上书城设计报告,基于安卓的网上商城手机APP设计与实现

    摘要: 近几年来,随着互联网和多媒体运营的持续和有效的迅猛发展,大多数人都开始选择在网上进行足不出户就可以品尝天下鲜的生活,Internet这个英语名词在人们的生活中变成了熟悉和时尚的冥思.人们的生活 ...

最新文章

  1. StringUtils中 isNotEmpty 和isNotBlank的区别
  2. 新型机器学习算法:正则化理解
  3. pythonfor循环100次_以写代学: python for循环 range函数 xrange函数
  4. 题目1417:变形金刚
  5. python黑帽编程视频_Python黑帽编程 3.4 跨越VLAN详解
  6. python常用的库与包_python常用到哪些库?
  7. python自学看什么书-如何自学Python ?自学看什么书比较好?
  8. 《oracle大型数据库系统在AIX/unix上的实战详解》讨论45 显示某个登录用户的信息...
  9. Java高级面试题!传智播客java基础入门pdf
  10. Hybrid Astar 算法剖析和实现(一)
  11. JDBC驱动(类型)
  12. jq ui 日历控件
  13. 快不快乐用计算机,快乐学计算机
  14. Android 仿今日头条、网易新闻的频道管理
  15. uniapp 引导页 启动页 闪屏页功能介绍及部分功能实现
  16. datadog ebpf模块 offset-guess.o 问题排查解决
  17. Android Audio混音实践篇
  18. 西安电子科技大学计算机834,西安电子科技大学834数据结构2021年硕士研究生招生考试自命题科目考试大纲...
  19. 三只松鼠事件竟是乌龙我们能不能给薇娅们一些耐心
  20. 第十八章 SQL函数 ASCII

热门文章

  1. [zz]Maya C++ API Programming Tips
  2. Linux性能调优、Linux集群与存储等
  3. 尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题。...
  4. Windows 下音频数据采集和播放
  5. 基于智能卡的嵌入式网络加密安全系统设计
  6. 损人不利己的飞鸽传书 部分代码公开
  7. 对于判断飞鸽传书2007来说是不够的
  8. 我们很需要“企业即时通讯”
  9. FreeBSD5.0内核 - 锁机制
  10. 结合PE格式对linker分析1