鹿溪大学 2024级本科毕业论文(设计)
题 目 基于Android的记账本1设计与实现
专 业 计算机
院 系 计算机科学学院
学 号 Xxx
姓 名 鹿溪
指 导 教 师 Xxx
答 辩 时 间 2024年06月
摘要
古往今来人们使用各种方式记账,如老一辈人使用书写的方式进行记账,到了二十一世纪随着信息化时代的到来,电脑软 件的普及,人们使用Excel或是其他软件进行电脑记账,但是以上方式都受限于时间和空间,不能随时随地的记账,耽误了时间 导致忘记记录。或者是需要后期运用大量的时间来进行统计和分析工作,从而致使人们无法养成记账的好习惯,更加无法达到 让用户合理消费的目的。所以急需一款能随时随地进行记账的产品,而手机应用软件APP能够满足其需求,它不再局限于时间和 空间。使用户自由的进行记账。
随着经济的发展,人们能选择的消费方式五花八门,拥有支付类APP也是种类繁多,在这样的前提下,研究一款适用于人们 日常消费记账的APP是十分急切的。本论文所述产品不仅能方便用户记录收支情况,用户清晰的看到自己的流水情况,分类消费 情况,总结自己的资产情况而且还能根据用户消费情况为其提供适合的产品最后本产品还有一个论坛专区,用户可以在里面进 行分享和交流。避免其购买无用产品的可能性。
本文介绍了“钱去哪了”APP的设计与实现。首先本APP是属于一个记账类APP,当用户注册并登录本APP时,用户可以在论 坛页面进行发帖,对经济或者记账习惯做出讨论,后台管理员看帖子的详情选择是否通过,用户在账单页面,可以对近期的消 费或者支出记账,账单页面左滑出现账单详情,用户更加清楚的看到自己那样消费最多,需要注意。购物页面是后台管理员根 据消费明细,综合给所有用户推荐他们可能喜欢的商品。分类页面则是用户对于某日消费能具体的查看比例。个人中心综合了 用户所有需要后台审核的信息。管理后台则主要负责:消费类型管理,商品管理,论坛管理,订单管理,用户管理以及消费明 细。
关键词: 记录,账单,APP,记账
关键词: Android,记录,账单,APP,记账
ABSTRACT
Through the ages people use a variety of ways to an account, such as older people use charge to an account in the form of written by the middle of the twentieth century with the advent of the era of information technology, the popularity of computer software, people use Excel or other computer accounting software, but the above methods are limited by time and space, can’t billing anytime and anywhere, delay the time to forget. Or need to use a lot of time later to carry out statistics and analysis, so that people can not develop a good habit of accounting, more can not achieve the purpose of allowing users to reasonable consumption. Therefore, it is in urgent need of a product that can keep accounts anytime and anywhere. However, mobile APP can meet its needs, which is no longer limited to time and space. The user is free to keep accounts. With the development of economy, people can choose a variety of consumption modes, and there are also a variety of payment apps. Under such a premise, it is very urgent to study an APP applicable to People’s Daily consumption accounting. The products described in this paper can not only facilitate users to record income and expenditure, users can clearly see their own flow situation, classify consumption situation, summarize their own assets, but also can provide suitable products according to the consumption situation of users. Avoid the possibility of buying useless products. This paper summarizes the design and implementation of the App “Where the Money Goes”. First this APP is to belong to a class of charge to an account APP, when a user register and log in this APP, users can post on the BBS page, on the economy or an account used to make a discussion, administrators see details of the post to choose whether to pass, user page to the bill, can for the recent consumption, or spending bills left sliding billing details, most users more clearly see their consumption, need to pay attention to. The shopping page is a backstage administrator based on the consumption details to recommend to all users the products they may like. Classified page is the user for a day of consumption can view the specific proportion. Personal overall heart comprehensive user all need background audit information. The management background is mainly responsible for: consumption type management, commodity management, forum management, order management, user management and consumption details.
Keywords: Android; record the bill, Forum, shopping goods
目录
第一章 绪论 9
1.1 研究背景和意义 9
1.1.1 研究背景 9
1.1.2 研究目的 10
1.2 国内外的研究现状 11
1.3 记账类APP竞品分析 13
第二章 系统开发环境与相关技术 15
2.1 系统开发的环境 15
2.2 系统开发技术介绍 15
2.2.1 Java介绍 15
2.2.2 MVC简介 18
2.2.3 SQLite简介 20
2.3安卓环境的搭建 21
2.3.1 Android studio软件下载 21
2.3.2 jdk安装 22
2.3.3 Android SDK安装 23
2.3.4创建AVD 24
2.4 可行性分析 26
2.4.1 技术可行性 26
2.4.2 法律可行性 26
2.4.3 操作可行性 27
2.5 需求分析 27
第三章 记账本概要设计 28
3.1系统功能设计 28
3.2数据库设计 30
3.2.1创建数据库 30
3.2.2数据库E-R图 35
3.2.3 数据库表结构设计 36
第四章 记账本1功能的实现 38
4.1 开发环境的配置与检查 38
4.2 App安全页面设计 41
4.2.1 登录密码页面 41
4.2.2 重置密码 44
4.3账单页面管理 45
4.3.1 单日账单 45
4.3.2 年度账单 48
4.3.3 扫码记账功能 51
4.4 App图表管理 54
4.4.1 当前收入饼状图 54
4.4.2 当前支出饼状图 56
4.4.3 年度收入支出柱状图 58
4.4.4 年度收入报表 62
4.4.5 年度支出报表 63
4.5设置管理 65
4.5.1收入资产设置 65
4.5.2支出资产设置 68
4.5.3 预算设置 70
4.5.4账户设置 73
4.5.5提醒设置 75
4.5.6关于应用 79
4.5.7退出应用 80
new MaterialDialog.Builder(this) 81
第五章 总结 82
附录 82
JDK Java Development Kit 82
参考文献 84
第一章 绪论
1.1 研究背景和意义
1.1.1 研究背景
近年来,随着如今生活购物的方便,人们可选购的产品与服务产生出多样化,使得许多人的消费不够清楚明了,不利于个 人理财。再加上移动互联的迅猛发展,手机支付的普及,许多人使用花呗支付、京东白条、美团月付等等,进行超前消费,使 人们对自己在各类APP的消费不明确,仅仅只关注自己余额,只有到还款日期才发现自己的消费金额巨大,造成无法一次还清需 要分期还款,产生更多的费用的情况。并且没有现金交易让人们对这类消费弱化了感受。最后由于不少人对于自己的消费没有 节制,以至于即使不在自己消费能力范围内也要通过各种借贷软件去过度消费,从而导致生活压力的不断增加,严重影响了正 常生活。 极大部分大学生的消费能力在2000以下,并且没有人是完全靠自己养活自己的。仅有11.36%的大学生的生活费又富有的 ,所以其他大部分同学是需要一个消费APP来规划自己的消费达到又富有的状态。购置衣服和生活用品是出伙食外的最大消费。 我们可以从这两个方面进行计划。并且仅有6.82%的同学是全部计划好在花钱的。这也体现了需求。而从不使用预支付方式付款 的人仅有15.91%,所以我们要减少同学使用预支付方式的比例,合理的规划每月消费。最后还是有高达68.18%的人希望有消费 过量提醒的功能,这说明很大一部分同学不希望自己没有节制的消费。[1] APP的概述 随着移动设备普遍性的使用,手机APP的发展也到了一个新的时代,出现了许多可以由用户自行选择安装的APP。有各种分 类比如影音视听、实用工具、聊天社交、图书阅读、时尚购物和学习教育等[2]。其次硬件设施的升级,智能手机的出现给了移 动APP更大的发展空间,并且由于手机内存的不断增大,每个人的手机中都拥有数十款手机APP,其给手机APP提供了较大的生存 空间。并且许多大品牌手机其拥有自己的操作系统,独立的处理器让APP的开发标准化,操作流程化以及表现多元化。
如果说手机的普遍使用给APP创造了生存空间,那么触摸屏手机的到来就是给APP提供了裂变发展的机会,使得越来越多的 人喜欢在手机上动一动就能达成之前需要用手写用笔记的传统方式。i0S、Android 等智能操作系统的出现,促使了更多APP的 诞生,相较于之前以游戏娱乐为主的APP类型,资讯工具类APP开始增多[3]。APP作为一种虚拟产品已经被广大用户所接受,用 户愿意为APP所营造的服务与体验去付费APP Store以及Android Market. 上的APP数量都已突破十万,其中不乏大量付费APP。
1.1.2 研究目的
进入到新世纪后,使用Android技术,设计并实现一个“钱去哪了”APP。使用者注册并登录之后,根据自己每笔消费情况实现支出记账,收 入记账、流水显示、支出收入分类图表(比如饮食,化妆,租房和服装等所占比例)、各类账号资产情况,商品推荐和论坛讨 论。实现帮助用户清晰明了的知道自己本月或者总体的收支情况,明确的知道自己本月最大收入和最大支持分别是哪一项。用 户自己看到账单之后分析这一项使用是否合理进而帮助用户完成合理化消费的可能,避免用户超前消费从而进行的一些借贷活 动。并且在论坛区域,被管理员审核通过的帖子大多都是一些积极记账带来的收获分享帖子,用户之间形成一种良性竞争,加 深用户记账的习惯。 选用手机APP作为本产品的载体是因为互联网时代,手机APP正在影响我们的生活,改变我们使用传统工具的习惯,建立行互 联网时代新型传播结构。手机APP满足了人们工作学习和日常生活的需求,符合如今快节奏的更高效的社会发展速度。它不但能 实现简单达到目的的需求,还在快速的入侵人们的生活,在公交地铁无处不见的低头族,正是被手机APP吸引到无法自拔的人。
1.2 国内外的研究现状
当今社会是一个信息社会,人们无论何时何地都在处理信息,你看的报纸就是信息,你看到的广告就是信息,电视就是信息,浏览互联网就是信息,当代人只是生活在一个“信息海洋”里。那么多有用和无用的信息,人们在信息丰富的社会中,难免会忘记一些重要信息,有时掉落手机,有时掉落电话簿或笔记本什么的,这些“信息载体”中可能包含着重要的个人信息。如何存储这些有用的信息以避免遗忘或丢失,如何有序地组织和管理这些有用的信息以帮助生活决策,这正是信息管理软件想要解决的问题[1]。
从21世纪初开始,无处不在的计算将打破计算机的传统概念:各种移动更方便、功能更轻松、更多样化的计算机设备将出现,在需要时,它们可以随时无线连接到移动数据通信网络,以便有效地交换信息并获得各种服务。此设备称为无线设备。移动设备最基本的特征是移动性,即能够利用无线电波、微波或红外线等传输介质,使通信中的设备在一定范围内自由移动,其位置不受约束,从而达到信息传输和交换运动中通信双方中至少一方的目的。移动设备已经存在很长时间了,但它们的增长速度比人们预期的要快得多。现如今,移动设备大行其道,全球有超过十亿部移动电话正在被使用,并且这个数目正在逐渐增加。在除美国之外的每个发达国家,拥有手机的人数比拥有计算机的人数更多[2]。
而目前,随着移动设备越来越普及及移动硬件的提升,移动设备的功能越来越完善移动设备的系统平台也日渐火热起来。目前国内最常见的移动开发平台有 Symbian,iPhone,Windows Phone 以及Android。如今国内外都有非常多的Android 系统的用户。自从2011年第一季度,Android 在全球份额首次超过 Symbian,跃居全球第一。截止 2012年2月据,Android 占据全球智能手机操作系统市场 52.5%的份额,中国市场占有率为68.4%[3]。
考虑到如今手机系统的发展现状,以及 Android 平台系统自身所拥有的优势。因此,基于安卓平台开发一款记账本具有较大的意义和可行性。
1.3 记账类APP竞品分析
首先,记账APP的主要功能是帮助人们进行记账,全面的记录用户的每一笔收入、支出情况,并且让用户直观的看到自己的 收支明细。并且随着信息技术的发展,记账类APP可以为用户随时随地记录,比以前书本类记账方便许多。 根据作者使用随手记、鲨鱼记账以及挖财等记账类APP的使用体验,随手记下载量7490万、鲨鱼记账2626万、挖财记账 2090万(数据来源于酷传数据)。随手记记账功能全面,能够给各类人群提供需求,信息安全性高,用户量庞大,下载体验的 结果是要求获取一些看似跟记账没有关系的手机权限,并且在使用过程中经常容易弹出广告,用户体验不是很好。缺点:拥有 太多理财功能,过于专业对于仅仅只是需要记账的用户来说,其占用太多手机内存,并且广告信息也偏多。鲨鱼记账极简的操 作,一目了然发图表,可以设定预期金额超值时进行提醒,但是其突变显示仅仅只有周月年不能具体到日,且没有扇形图显示比例不够明确。挖财记账页面美观,结构简单,操作方便,用户上手时间快,但是其让用户可以将资金放入,但作者查询其背 后并没有大集团为其保驾护航,所以应该提高其数据和投资的安全性,并且是以理财功能为核心的并不是简单的记账功能。 对于上述商品,其都有一定的优点但也有不可忽略的缺点,但是这些软件都有一个共同的缺点是不够单一,现在几乎所有 的记账软件都要包含理财,资金存放的问题,并不是单纯的为用户提供一个操作简单,所占内存小的记账APP,而本文所述产品却能很好的满足用户对单一记账软件的需求。
第二章 系统开发环境与相关技术
2.1 系统开发的环境
Android 一词的本义指“机器人”,同时也是 Google 于2007 年11月5日宣布的基于Linux 平台的开源手机操作系统的名称,该平台由操作系统、中间件、用户界面和应用软件组成,号称是首个为移动终端打造的真正开放和完整的移动软件。Android 的上层应用程序是用 Java 语言开发,同时还需要基于 Dalvik 虚拟机,所以,Google 公司推荐使用主流的 Java 继承开发环境 Android studio。只有 Android studio 还不够,因为是使用 Java 语言进行开发, 还应该有由 SUN 公司提供的 Java SDK(其中包括JRE:Java Runtime Environment)。此外,Android 的应用程序开发和Java 开发有较大区别的,所以还需要有 Google 提供的AndroidSDK。为Android开发提供开发工具的升级或者变更,是Android studio 下开发工具的升级下载的工具。简言之,需要以上软件,才能搭建 Android 开发环境,从而进行 Android 应用程序的开发[4]。
2.2 系统开发技术介绍
2.2.1 Java介绍
Java 是一种简单的,跨平台的,面向对象的,分布式的,解释的,健壮的安全的,结构的中立的,可移植的,性能很优异的多线程的,动态的语言。
Java 编程语言的风格十分接近 C、C++语言。在 Java SE 1.5 版本中,Java 引入了泛型编程(Generic Programming)、类型安全的枚举、不定长参数和自动装/拆箱等语言特性,Java 不同于一般的编译执行计算机语言和解释执行计算机语言。它首先将源代码编译成二进制字节码(bytecode),然后依赖各种不同平台上的虚拟机来解释执行字节码,从而实现了“一次编译、到处执行”的跨平台特性。不过,每次的编译执行需要消耗一定的时间,这同时也在一定程度上降低了 Java 程序的运行效率。但在 J2SE 1.4.2发布后,Java 的执行速度有了大幅提升。与传统程序不同,Sun 公司在推出 Java 之际就将其作为一种开放的技术。全球数以万计的 Java 开发公司被要求所设计的 Java 软件必须相互兼容。“Java 语言靠群体的力量而非公司的力量”是 Sun 公司的口号之一,并获得了广大软件开发商的认同。这与微软公司所倡导的注重精英和封闭式的模式完全不同。 Sun 公司对 Java 编程语言的解释是:Java 编程语言是个简单、面向对象、分布式、解释性、健壮、安全与系统无关、可移植、高性能、多线程和动态的语言。 Java平台是基于 Java 语言的平台[5]。
Java 的特点总结如下:
1.平台无关性
平台无关性是指 Java 能运行于不同的平台。Java 引进虚拟机 原理,并运行于虚拟机,实现不同平台的Java 接口之间。使用 Java 编写的程序能在世界范围内共享。Java的数据类型与 机器无关,Java 虚拟机 Java Virtual Machine) 是建立在硬件和操作系统之上,实现 Java 二进制代码的解释执行功能, 提供于不同平台的接口的。
2.安全性
Java 的编程类似C++,学习过 C++的读者将很快掌握Java 的精髓。Java 舍弃了C++的指针对存储器地址的直接操作,程序运行时,内存由操作系统分配,这样可以避免病毒通过指针侵入系统。Java 对程序提供了安全管理器,防止程序的非法访问。
3.面向对象
Java 吸取了C++面向对象的概念,将数据封装于类中,利用类的优点,实现了程序的简洁性和便于维护性。类的封装性、继承性等有关对象的特性,使程序代码只需一次编译,然后通过上述特性反复利用。程序员只需把主要精力用在类和接口的设计和应用上。Java 提供了众多的一般对象的类,通过继承即可使用父类的方法。在 Java 中,类的继承关系是单一的非多重的,一个子类只有一个父类,子类的父类又有一个父类。Java提供的 0bject 类及其子类的继承关系如同一棵倒立的树形,根类为 0bject 类,Object类功能强大,经常会使用到它及其它派生的子类。
4.分布式
Java 建立在扩展 TCP/IP 网络平台上。库函数提供了用 HTTP FTP 协议传送和接受信息的方法。这使得程序员使用网络上的文件和使用木机文件一样容易。
5.健壮性
Java 致力于检查程序在编译和运行时的错误。类型检查帮助检查出许多开发早期出现的错误。Java 自己操纵内存减少了内存出错的可能性。Java 还实现了真数组,避免了覆盖数据的可能,这些功能特征大大提高了开发 Java 应用程序的周期。并且Java. 还提供了 Null 指针检测、数组边界检测、异常出口、Byte code 校验等功能。
6.解释型
我们知道 C,C++等语言,都是针对 CPU 芯片进行编译,生成机器代码,该代码的运行就和特定的 CPU有关。Java 不像 C或 C++,它不针对 CPU 芯片进行编译,而是把程序编译成称为字节码的一种“中间代码”。字节码是很接近机器码的文件,可以在提供了java 虚拟机(JVM)的任何系统上被解释执行。
7.动态
JAVA 程序的基本组成单元就是类,有些类是自己编写的,有些是从类库巾引入的,而类又是运行时动态装载的,这就使得 Java 可以在分部环境中动态的维护程序及分类而不像 C++那样,没档期类库升级以后,如果想让程序具有新类库提供的功能,就需要修改程序,重新编译[6]。
2.2.2 MVC简介
MVC 其实是一种架构设计,通过这种分层技术不管是在开发还是在后期的运维都更加的简洁高效。
MVC 提高了 Java 开发的代码复用性,避免了重复性开发。它有效地帮助开发人员实现业务开发中的事务管理。
MVC 实际就是 Model (模型)、View (视图)、Controller (控制器)。虽然叫 MVC但实际执行顺序是: CMV、CV 或直接 V。ASP 或者 JSP 这类语言是 M 和 V 的桥梁,由于 C 的作用,最后将数据显示出来。这三层之间的关系图如图 2-2 所示:
图 2-2 三层之间的关系图
先说视图层(View),将处理结果写入响应包中,它可以说是一个 xml 代码。Xml其实在 MVC 当中充当了这个 View 这一层的技术解决方案。其次模型层(Model),它其实就是数据,可以是 SOL 出来的数据最后是控制层(Controller),就是完成业务处理。它细化为两层: (1)DAO 层: 用来对数据库直接操作封装。(2)Service 层: 主要是来调用 Dao 层来完成业务的实现,负责管理所调用的 DAO 层的事务的管理。Controller 组件将传入的用户请求分派给 Model 中的适当数据分析逻辑函数,Model组件从分层数据库检索或插入所需的信息,并将其传递给控制器,控制器反过来将响应发送给 View 组件。View 组件按照技术来呈现信息。Controller 组件是使用 Java servlet 开发的[8]。
2.2.3 SQLite简介
SQLite是一个轻量级、跨平台的关系型数据库。SQLite的很小,它的数据库就是一个文件,但是它并不缺乏功能。不需要复杂的安装或管理。SQLite事务是完全兼容ACID的,允许从多个进程或线程安全访问。SQLite特别适合为单个应用程序和设备提供本地数据存储,使用很简单,将sqlite3.exe可执行文件复制到目标计算机上就可以运行它,新版本对SQL支持比较完善了,因此可以很方便的用来学习SQL。
主要特色:
轻量级。SQLite和C/S模式的数据库软件Q不同,它是进程内的数据库引擎因此不存在数据库的客户端和服务器。使用SQLite一般只需要带上它的一个动态库,就可以享受它的全部功能。而且那个动态库的尺寸也挺小,以版本3.6.11为例,Windows下487KB、Linux下347KB。
绿色软件。SQLite的另外一个特点是绿色: 它的核心引擎本身不依赖第三方的软件,使用它也不需要“安装”。所以在部署的时候能够省去不少麻烦。
单一文件。所谓的“单一文件”,就是数据库中所有的信息 (比如表、视图、触发器、等)都包含在一个文件内。这个文件可以copy到其它目录或其它机器上,也照用不误。
跨平台/可移植性。可在 UNIX、Linux,Mac OS-X,Android,iOs和 Windows中运行[7]。
2.3安卓环境的搭建
2.3.1 Android studio软件下载
Android Studio(简称AS)是谷歌推出的一个Android集成开发工具,基于IntelliJ IDEA. 类似 Eclipse ADT,Android Studio 提供了集成的 Android 开发工具用于开发和调试。AS能够在Linux、Windows、macOS上运行,支持Java、Kotlin、Flutter等语言开发。
在IDEA的基础上,Android Studio 提供:
基于Gradle的构建支持
Android 专属的重构和快速修复
提示工具以捕获性能、可用性、版本兼容性等问题
支持ProGuard 和应用签名
基于模板的向导来生成常用的 Android 应用设计和组件
功能强大的布局编辑器,可以让你拖拉 UI 控件并进行效果预览。[10]
AS官网:developer.android.google.cn/studio
2.3.2 jdk安装
JDK(Java Development Kit)是 Sun Microsystems 针对 Java 开发员的产品。自从Java 推出以来,JDK 已经成为使用最广泛的Java SDK。JDK 是整个 Java 的核心,包括了Java 运行环境,Java 工具和 Java 基础的类库。JDK 是学好 Java 的第一步。而专门运行在x86 平台的Jrocket 在服务端运行效率也要比 Sun JDK 好很多。从SUN的JDK5.0开始,提供了泛型等非常实用的功能,其版本也不断更新,运行效率得到了非常大的提高。[9]
首先按提示完成 SDK 安装,然后设置环境变量(非必须)
1.我的电脑->属性->高级->环境变量->系统变量中添加以下环境变量:
2.JAVA_HOME 值为:G: Android\Java\jdk1.8.0 21(我所安装JDK 的目录)
3.CLASSPATH
值:.;%JAVA HOME%\lib\tools.jar;%JAVA HOME% lb\dt.jar;%JAVA HOME%\bin;4.Path:在开始追加%JAVA HOME%\bin;
安装完成之后,检查JDK 是否安装成功。打开cmd 窗口,输入 java -version 查看 JDK 的版本信息。出现下面的画面表示安装成功了,如图2.3.2所示:
图2.3.2安装成功显示截图
2.3.3 Android SDK安装
SDK:(software development kit)软件开发工具包。被软件开发工程师用于为特定的软件包、软件框架、硬件平台、操作系统等建立应用软件的开发工具的集合。因此,Android SDK 指的既是 Android 专属的软件开发工具包[11]。
下载完成后解压到任意路径运行 SDK Setup.exe,点击Available Packages。选择希望安装的 SDK 及其文档或者其它包,按需点击下面选项(开始下载安装所选包 )在用户变量中新建 PATH 值为:Android SDK 中的 tools 绝对路径(本机是G:\SDK\android-sdk-windows\tools).
完成按“确定”后,重新启动计算机。重启计算机以后,进入 cmd 命令窗口,检查SDK 是不是安装成功。
运行 adb 出现参数选择,表明安装成功。如图2.3.3所示。[12]
图2.3.3 Android SDK安装成功运行界面
2.3.4创建AVD
为使 Android应用程序可以在模拟器上运行,必须创建 AVD。在Android studio中[13]。
1、选择DevicesManager > Create Devices
2、填入 Name,选择 Target的 API,SD Card 大小任意,其他目前保持默认值
3、点击 Create AVD 即可完成创建 AVD,如图2.3.4所示。综上一切完成后安卓环境搭建完成
图2.3.4 AVD的创建完成
2.4 可行性分析
为了将记账本实现,对该记账本进行可行性分析,这是决定开发系统成功的关键。这样不仅能帮助在开发时减少一定的成本,也能避免一些编程时对资源的浪费。
2.4.1 技术可行性
在开发系统之前进行技术可行性研究,是为了对记账本开发环境和开发技术有一定的可行性规划,有了确定合理的规划后,进行系统的编写,从而提高开发效率。
记账本涉及技术主要有:开发环境,开发架构,数据库等具体分析如下:
开发环境使用的是 Android studio 平台,是以 Android studio 为基础添加独有插件的企业级集成开发软件。现在 Java 越来越流行,Android studio 也就被各大企业广泛使用。Android studio 拥有 Java,Java EE 的插件。数据库使用 SQLite 数据库,其具有良好稳定的环境,保证了数据的安全性。SQLite 直奉行简单易用的原则,既能直接在平台上操作,又能通过编写 SQL 语言将数据信息化。
这些方面都在行业中被广泛使用,因此,本系统开发在技术上是可行的[14]。
2.4.2 法律可行性
法律可行性系统开发使用的软件都是在其官方网站中进行下载后,按照软件安装步骤进行安装后,才使用于本系统的开发。在 2008 年,微软公司就推出了两条关于正版软件的通知,为了保护那些不知情而安装、使用盗版软件用户。盗版软件是通过非法手段对正版软件进行复制或者仿造而成的。盗版软件只有当前一个版本,没有后期的升级和维护,失去了使用保障。因此,本系统是符合法律效应的,在法律方面是可行的。
2.4.3 操作可行性
该项目采用Android studio作为开发平台,sqlite为数据库,java语言编写,操作简单易懂。而且当下大多数计算机都能运行该系统,并且该系统界面简单,提示信息完整。该系统的主要使用者是学习者和教学者,伴随着移动应用的普及,大多数人都已无形中具备了使用计算机或者手机的能力。用户在操作上是不存在障碍的,所以是可行的。
2.5 需求分析
该系统是一个基于学校记账本针对用户的手机客户端。它是为本软件的持有者提供对记账本一些功能进行基本操作。
第三章 记账本概要设计
3.1系统功能设计
在系统功能这一块主要涉及了App的账单、图表、设置等功能,如图3.1所示。
图3.1.1 App功能结构图
图3.1.2技术路线图
图3.1.3思路图
图3.1.4数据流图
图3.1.5记账ER图
3.2数据库设计
数据库的表是属于数据模型,用来描述数据的结构最清晰不过了。
图3.2实体属性E-R图
3.2.1创建数据库
数据库使用的是Android自带的关系型数据库SQLite。SQLite最大的特点是你可以把各种类型的数据保存到任何字段中,而不用关心字段声明的数据类型是什么。使用SQLiteDatabase操作SQLite数据库:Android提供了一个名为SQLiteDatabase的类,该类封装了一些操作数据库的API,使用该类可以完成对数据进行添加(Create)、查询(Retrieve)、更新(Update)和删除(Delete)操作(这些操作简称为CRUD)。execSQL()和rawQuery()方法。 execSQL()方法可以执行insert、delete、update和CREATE TABLE之类有更改行为的SQL语句; rawQuery()方法用于执行select语句。
(1)数据库代码
private SQLiteDatabase db;
@Override
public void onCreate(SQLiteDatabase db) {
this.db = db;
db.beginTransaction();
try {
db.execSQL(create_account_tbl);
db.execSQL(create_user_tbl);
db.execSQL(create_zichan_tbl);
db.execSQL(create_pay_tbl);
initDefault();
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally {
db.endTransaction();
}
db.execSQL("DROP TABLE IF EXISTS account_table");
db.execSQL("DROP TABLE IF EXISTS user_table");
db.execSQL("DROP TABLE IF EXISTS zichan_table");
db.execSQL("DROP TABLE IF EXISTS pay_table");
onCreate(db);
} catch (Exception e) {
Log.d(TAG, "onUpgrade Exception" + e.toString());
}
}
/**
* 模糊查找
*/ if(!TextUtils.isEmpty(accountType)&&TextUtils.isEmpty(zcType)){
sqlStr = "select * from account_table where " +
"user=" + "\"" + user + "\""
+ " and datetime(time) between datetime('" +minTime+"') and datetime('"+maxTime+"')"
+ " and accountType=" + "\"" + accountType + "\"";
}else if(!TextUtils.isEmpty(accountType)&&!TextUtils.isEmpty(zcType)){
sqlStr = "select * from account_table where "
+ "user=" + "\"" + user + "\""
+ " and datetime(time) between datetime('" +minTime+"') and datetime('"+maxTime+"')"
+ " and accountType= "+ "\"" + accountType + "\""
+ " and type= "+ "\"" + zcType + "\"";
}else if(TextUtils.isEmpty(accountType)&&TextUtils.isEmpty(zcType)){
sqlStr = "select * from account_table where " +
"user=" + "\"" + user + "\""
+ " and datetime(time) between datetime('" +minTime+"') and datetime('"+maxTime+"')";
}else if(TextUtils.isEmpty(accountType)&&!TextUtils.isEmpty(zcType)){
sqlStr = "select * from account_table where " +
"user=" + "\"" + user + "\""
+ " and datetime(time) between datetime('" +minTime+"') and datetime('"+maxTime+"')"
+ " and type=" + "\"" + zcType + "\"";
}
queryAllAccounts = db.rawQuery(sqlStr, null);
} catch (Exception e) {
Log.d(TAG, "queryDB Exception " + e.toString());
}
return queryAllAccounts;
}
public void deleteSinglePay(String name) {
try {
db = getWritableDatabase();
db.delete("pay_table", "name=?", new String[]{name});
} finally {
closeDb();
}
}
ContentValues cv = new ContentValues();
cv.put("name", "工资收入");
cv.put("type", "income");
db.insert("zichan_table", null, cv);
cv = new ContentValues();
cv.put("name", "股票收入");
cv.put("type", "income");
cv.put("id", 2);
db.insert("zichan_table", null, cv);
cv = new ContentValues();
cv.put("name", "其他收入");
cv.put("type", "income");
db.insert("zichan_table", null, cv);
cv = new ContentValues();
cv.put("name", "日常购物");
cv.put("type", "outcome");
db.insert("zichan_table", null, cv);
cv = new ContentValues();
cv.put("name", "餐饮开销");
cv.put("type", "outcome");
db.insert("zichan_table", null, cv);
cv = new ContentValues();
cv.put("name", "购置衣物");
cv.put("type", "outcome");
db.insert("zichan_table", null, cv);
cv = new ContentValues();
cv.put("name", "娱乐开销");
cv.put("type", "outcome");
db.insert("zichan_table", null, cv);
cv = new ContentValues();
cv.put("name", "交通出行");
cv.put("type", "outcome");
db.insert("zichan_table", null, cv);
cv = new ContentValues();
cv.put("name", "水电煤气");
cv.put("type", "outcome");
db.insert("zichan_table", null, cv);
cv = new ContentValues();
cv.put("name", "其他花费");
cv.put("type", "outcome");
db.insert("zichan_table", null, cv);
cv = new ContentValues();
cv.put("name", "支付宝");
db.insert("pay_table", null, cv);
cv = new ContentValues();
cv.put("name", "微信");
db.insert("pay_table", null, cv);
}
}
3.2.2数据库E-R图
考虑一个问题,在分析其中的关系时,确定了实体、属性,在制作ER图。脑海里清晰的实体与属性之间的关系,实体与实体之间的关系,在建立数据库时才会有更好的脉络。
1.用户注册E-R图
图3.3注册登录E-R图
2.账单E-R图
图3.4账户E-R图
3.图表E-R图
图3.5图表E-R图
3.2.3 数据库表结构设计
在数据库的选择上考虑到Android数据的以下几点:
Android自带的轻型数据库将带给用户更好的体验。
SQLite虽然很小巧,但是支持的SQL语句不会逊色于其他开源数据库并且摆脱了运营商的束缚让终端有了更大的权益。
Android开发的平台对移动终端厂商的兼容性大大提高,更为便捷。
SQLite,是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合
1.用户登录模块信息表tb_user。主要是记录了便捷记账本App中用户的密码类型的基本信息与安全问题,表的结构如下表3.1所示。
表3.1用户模块信息表(t_user
表3.1 用户模块信息表(t_user)
列名 | 数据类型 | 允许空 | 默认值 | 是否主键 | 说明 |
---|---|---|---|---|---|
id | varchar(20) | 否 | 空 | 是 | 主键 |
username | varchar(20) | 否 | 空 | 否 | 用户姓名 |
password | varchar(20) | 否 | 空 | 否 | 用户密码 |
2.账户模块信息表zichan_table。记录了便捷记账本App中账户的四种基本类型。表的结构如下表3.2所示。
表3.2 类型设置信息表(leixin_table)
列名 | 数据类型 | 允许空 | 默认值 | 是否主键 | 说明 |
---|---|---|---|---|---|
id | varchar(20) | 否 | 空 | 是 | 主键 |
z_type | Varchar(10) | 否 | 空 | 否 | 支出类型 |
s_type | Varchar(10) | 是 | 空 | 否 | 收入类型 |
说明:
- 用户模块信息表(t_user):记录了用户的基本信息,包括用户ID、用户名和密码。
- 类型设置信息表(leixin_table):记录了便捷记账本App中账户的支出类型和收入类型。
3.消费支出信息表tb_pay_income。主要是记录了便捷记账本App里收入与支出的基本信息,表结构如下表3.3所示。
表3.3消费支出信息表(tb_ pay_income)
列名 | 数据类型 | 允许空 | 默认值 | 是否主键 | 说明 |
---|---|---|---|---|---|
id | int | 否 | 空 | 是 | 主键 |
money | varchar(100) | 否 | 空 | 否 | 金额 |
remark | varchar(100) | 是 | 空 | 否 | 备注 |
type | varchar(10) | 否 | 空 | 否 | 支出选择 |
account_id | integer | 是 | 空 | 否 | 账户类型 |
time | Integer | 否 | 空 | 否 | 支出日期 |
这个表格清晰地展示了消费支出信息表(tb_pay_income)的各个列名、数据类型、是否允许为空、默认值、是否为主键以及每个列的说明。
第四章 记账本1功能的实现
4.1 开发环境的配置与检查
1.下载检查Android studio最新版本
2.在Android studio中菜单选项点击help选项,选择检查最新版本安装选项
图4.1 配置页面
3.进入安装检查Android SDK插件
图4.2安装页面
4.下载完成后单击install,电脑会自动下载
5.下载完成后点击Android中的file菜单中的new,选择import project选项并找到目录
图4.3选项引导页面
图4.4 目录页面
6.单击OK后,项目导入成功。
图4.5 导入项目页面
4.2 App安全页面设计
4.2.1登录密码页面
1.为了保护用户的隐私与安全性,用户可以设置登录密码,只有输入正确的密码才能进入,密码不正确会有提示,如果忘记密码还可以通过重置密码来更改密码。
用户登录顺序图
2.App页面运行效果图如图4.7所示
图4.7 App安全页面
3.App安全页面的关键代码:
public void onClick(View view) {
switch (view.getId()) {
case R.id.button_login:
String username = mEtUserName.getText().toString();
if (username.isEmpty()) {
showUserNameEmptyError();
return;
}
String pwd = mEtPwd.getText().toString();
if (pwd.isEmpty()) {
showUserPasswordEmptyError();
return;
}
progressDialogShow();
if (DBProvider.getInstance(mAct).isUserExist(username, pwd)) {
//验证成功
mApp.setCurrentUser(DBProvider.getInstance(mAct).getSingleUserFromDB(username, pwd));
//记住密码
if (mCkRemberPwd.isChecked()) {
SPUtils.setParam(mAct, C.SP.account,
mEtUserName.getText().toString());
SPUtils.setParam(mAct, C.SP.pwd,
mEtPwd.getText().toString());
} else {
SPUtils.setParam(mAct, C.SP.account, "");
SPUtils.setParam(mAct, C.SP.pwd, "");
}
progressDialogDismiss();
//进入主界面
Intent mainIntent = new Intent(mAct,
TabsActivity.class);
startActivity(mainIntent);
mAct.finish();
} else {
// 提示错误
progressDialogDismiss();
showLoginError();
}
break;
case R.id.button_register:
mFragmentCallBack.fragmentCallBack(LoginActivity.JUMP_2_REG, null);
break;
case R.id.login_button_reset_password:
mFragmentCallBack.fragmentCallBack(LoginActivity.JUMP_2_RESET, null);
break;
default:
break;
}
}
}
4.2.2 重置密码
1.为了提高App的应用性,重置密码可以通过重置密码来重新设置自己的密码,极大地提高了用户的体验性。如果密保不正确则无法获取到正确的密码提示。
2.重置密码时获得正确的密码效果图如图4.8所示:
图4.8 重置密码页面
3.重置密码页面的关键代码:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_modify_pwd, container, false);
mTxBack = (TextView) rootView.findViewById(R.id.rl_top_btn_back);
mEdOld = (EditText) rootView.findViewById(R.id.et_pwd_old);
mEdNew = (EditText) rootView.findViewById(R.id.et_pwd_new);
mEdNewR = (EditText) rootView.findViewById(R.id.et_pwd_new_repeat);
mEtUserName = (EditText) rootView.findViewById(R.id.editText_register_username);
mBtnModify = (Button) rootView.findViewById(R.id.btn_pwd_modify);
modifyToggleOne = (ToggleButton) rootView.findViewById(R.id.modify_toggle_one);
modifyToggleTwo = (ToggleButton) rootView.findViewById(R.id.modify_toggle_two);
modifyToggleThree = (ToggleButton) rootView.findViewById(R.id.modify_toggle_three);
mBtnModify.setOnClickListener(this);
mTxBack.setOnClickListener(this);
modifyToggleOne.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
4.3账单页面管理
4.3.1 单日账单
1.单日账单页面有:查询时间、收入金额、支出金额、总计金额、账单类型等,可以增加账单类型。
2.App单日账单效果图如图4.9所示。
图4.9 单日账单页面
3.App单日账单页面的关键代码:
private void initFloatBtn() {
mFabActBtn = (FloatingActionButton) rootView.findViewById(R.id.fab_normal);
mFabActBtn.setButtonSize(FloatingActionButton.SIZE_NORMAL);
mFabActBtn.setImageDrawable(new IconicsDrawable(mAct, GoogleMaterial.Icon.gmd_add).color(Color.WHITE).actionBar());
mFabActBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//增加一则
showAdd();
}
});
}
private void doRefresh() {
mSwipeRefreshLayout.setRefreshing(true);
mAllList.clear();
//查询成功
mAllList = DBProvider.getInstance(mAct).getTypeBeanFromDB(mApp.getCurrentUser(),mComeType);
//更新到最新的列表
mApp.mTypeBeanInList = mAllList;
mAdapter = new TypeAdapter(mAct, mAllList, InComeFragment.this);
mRecyclerView.setAdapter(mAdapter);
//此次刷新结束
mSwipeRefreshLayout.setRefreshing(false);
}
private void showHandleList(final TypeBean info) {
new MaterialDialog.Builder(mAct)
.title(R.string.acount_handle_title)
.items(R.array.zichan_handle)
.itemsCallback(new MaterialDialog.ListCallback() {
@Override
public void onSelection(MaterialDialog dialog, View view, int which, CharSequence text) {
dialog.dismiss();
switch (which) {
case 0:
showDel(info);
break;
case 1:
showUpdate(info);
break;
}
}
})
.show();
}
private void showUpdate(final TypeBean typeBean){
new MaterialDialog.Builder(mAct).title(R.string.update_income)
.positiveText(android.R.string.ok)
.inputRange(2, 10)
.input(getString(R.string.update_income_hint), typeBean.getName(), false, new MaterialDialog.InputCallback() {
@Override
public void onInput(@NonNull MaterialDialog dialog, CharSequence input) {
typeBean.setName(input.toString());
DBProvider.getInstance(mAct).updateTypeBean(typeBean.getId(),typeBean);
SingleToast.showToast(getContext(),"收入资产项修改成功",2000);
doRefresh();
}
})
.positiveText(R.string.btn_confirm)
.negativeText(R.string.btn_cancel).show();
}
}
4.3.2 年度账单
1.点击年度账单,可以查看一整年的账单记录。
2.App年度账单效果图如图4.10所示:
图4.10年度账单页面
3.年度账单的关键代码:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_day, container, false);
initViews();
menuActivity = (TabsActivity) mAct;
Calendar localCalendar = Calendar.getInstance();
int year = localCalendar.get(Calendar.YEAR);
int month = localCalendar.get(Calendar.MONTH);
int day = localCalendar.get(Calendar.DAY_OF_MONTH);
if (day < 10) {
if (month + 1 < 10) {
qryTime = year + "-0" + (month + 1) + "-0" + day;
} else {
qryTime = year + "-" + (month + 1) + "-0" + day;
}
} else {
if (month + 1 < 10) {
qryTime = year + "-0" + (month + 1) + "-" + day;
} else {
qryTime = year + "-" + (month + 1) + "-" + day;
}
}
mTxTime.setText("查询时间: " + qryTime);
mTxQryType.setText("账单类型:所有");
return rootView;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
doRefresh();
}
private void initViews() {
initFloatBtn();
mTxTime = (TextView) rootView.findViewById(R.id.tx_qry_time);
mTxTotal = (TextView) rootView.findViewById(R.id.tx_total);
mTxQryType = (TextView) rootView.findViewById(R.id.tx_type);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(mAct));
mSwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipe_container);
mSwipeRefreshLayout.setColorSchemeColors(getResources().getColor(R.color.theme_accent));
4.3.3 扫码记账功能
1.进入账单页面,点击扫码记账,扫描二维码就可以实现账单记录。
2.扫码记账效果图如图4.11所示:
图4.11 扫码记账页面
3.扫码记账关键代码:
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// 保持Activity处于唤醒状态
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.capture);
hasSurface = false;
inactivityTimer = new com.terry.account.zxing.android.InactivityTimer(this);
beepManager = new BeepManager(this);
imageButton_back = (ImageButton) findViewById(R.id.capture_imageview_back);
imageButton_back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
@Override
protected void onResume() {
super.onResume();
cameraManager = new CameraManager(getApplication());
viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
viewfinderView.setCameraManager(cameraManager);
handler = null;
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
if (hasSurface) {
// activity在paused时但不会stopped,因此surface仍旧存在;
// surfaceCreated()不会调用,因此在这里初始化camera
initCamera(surfaceHolder);
} else {
// 重置callback,等待surfaceCreated()来初始化camera
surfaceHolder.addCallback(this);
}
beepManager.updatePrefs();
inactivityTimer.onResume();
source = com.terry.account.zxing.android.IntentSource.NONE;
decodeFormats = null;
characterSet = null;
}
4.4 App图表管理
4.4.1 当前收入饼状图
1.说明:当前收入饼状图,可以将当前收入形成饼状图的形式,当再次点击饼状图会变颜色。
2.当前收入饼状图页面如图4.12:
图4.12 当前收入饼状图页面
3. 当前收入饼状图页面关键代码:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
View rootView = inflater.inflate(R.layout.fragment_pie_chart, container, false);
chart = (PieChartView) rootView.findViewById(R.id.chart);
chart.setOnValueTouchListener(new PieChartFragment.ValueTouchListener());
generateData();
return rootView;
}
private void generateData() {
int numColumns = mAllList.size();
List<SliceValue> values = new ArrayList<>();
float totalMoney = 0f;
for (int i = 0; i < numColumns; ++i) {
AccountBean accountBean = mAllList.get(i);
totalMoney = totalMoney+Float.parseFloat(accountBean.getMoney());
}
for (int i = 0; i < numColumns; ++i) {
AccountBean accountBean = mAllList.get(i);
SliceValue sliceValue = new SliceValue(Float.parseFloat(accountBean.getMoney()), ChartUtils.pickColor());
sliceValue.setLabel(accountBean.getType()+"\n"+ Float.parseFloat(accountBean.getMoney())/totalMoney*100+"%");
values.add(sliceValue);
}
data = new PieChartData(values);
data.setHasLabels(true);
data.setHasCenterCircle(false);
data.setCenterText1("");
chart.setPieChartData(data);
}
private class ValueTouchListener implements PieChartOnValueSelectListener {
@Override
public void onValueSelected(int arcIndex, SliceValue value) {
// Toast.makeText(getActivity(), "Selected: " + value, Toast.LENGTH_SHORT).show();
}
4.4.2 当前支出饼状图
1.说明:每天的支出会有记录,当前支出饼状图就可以将支出形成相应的饼状图,再次点击也会进行颜色变化。
2.当前支出饼状图效果图如图4.13所示:
图4.13当前支出饼状图页面
3. 当前支出饼状图关键代码:
vate void generateData() {
int numColumns = mAllList.size();
List<SliceValue> values = new ArrayList<>();
float totalMoney = 0f;
for (int i = 0; i < numColumns; ++i) {
AccountBean accountBean = mAllList.get(i);
totalMoney = totalMoney+Float.parseFloat(accountBean.getMoney());
}
for (int i = 0; i < numColumns; ++i) {
AccountBean accountBean = mAllList.get(i);
SliceValue sliceValue = new SliceValue(Float.parseFloat(accountBean.getMoney()), ChartUtils.pickColor());
sliceValue.setLabel(accountBean.getType()+"\n"+ Float.parseFloat(accountBean.getMoney())/totalMoney*100+"%");
values.add(sliceValue);
}
data = new PieChartData(values);
data.setHasLabels(true);
data.setHasCenterCircle(false);
data.setCenterText1("");
chart.setPieChartData(data);
}
private class ValueTouchListener implements PieChartOnValueSelectListener {
@Override
public void onValueSelected(int arcIndex, SliceValue value) {
// Toast.makeText(getActivity(), "Selected: " + value, Toast.LENGTH_SHORT).show();
}
@Override
public void onValueDeselected() {
}
}
}
4.4.3 年度收入支出柱状图
1.此页面可以将一整年的收入支出情况形成相应的柱状图形式,收入为正数,支出为负数。
2. 年度收入支出柱状图效果图如图4.14所示:
图4.14 年度收入支出柱状图页面
3. 年度收入支出柱状图关键代码:
public ColumnChartFragment setList(List<AccountBean> allList) {
mAllList = allList;
return this;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
View rootView = inflater.inflate(R.layout.fragment_column_chart, container, false);
chart = (ColumnChartView) rootView.findViewById(R.id.chart);
chart.setOnValueTouchListener(new ColumnChartFragment.ValueTouchListener());
chart.setValueSelectionEnabled(true);
generateData();
return rootView;
}
private void generateData() {
int numSubcolumns = 1;
int numColumns = mAllList.size();
List<Column> columns = new ArrayList<>();
List<SubcolumnValue> values;
List<AxisValue> axisValues = new ArrayList<>();
for (int i = 0; i < numColumns; i++) {
values = new ArrayList<>();
AccountBean accountBean = mAllList.get(i);
for (int j = 0; j < numSubcolumns; ++j) {
Float num;
String lable;
int color;
if (accountBean.getAccountType().equals("outcome")) {
//num = -Integer.valueOf(accountBean.getMoney());
num = -Float.valueOf(accountBean.getMoney());
lable = accountBean.getType() + "\n" + (num) + "元";
color = ChartUtils.COLOR_RED;
} else {
//num = Integer.valueOf(accountBean.getMoney());
num = Float.valueOf(accountBean.getMoney());
lable = accountBean.getType() + "\n" + num + "元";
color = ChartUtils.COLOR_GREEN;
}
SubcolumnValue subcolumnValue = new SubcolumnValue(num, color);
subcolumnValue.setLabel(lable);
values.add(subcolumnValue);
}
axisValues.add(new AxisValue(i).setLabel(accountBean.getTime()));
Column column = new Column(values);
column.setHasLabels(true);
columns.add(column);
}
data = new ColumnChartData(columns);
Axis dataAxis = new Axis(axisValues).setName("收支时间").setHasLines(true).setMaxLabelChars(numColumns)
.setTextColor(ChartUtils.COLOR_RED);
data.setAxisXBottom(dataAxis);
Axis axisY = new Axis().setHasLines(true);
axisY.setName("收支金额");
data.setAxisYLeft(axisY);
chart.setColumnChartData(data);
}
private class ValueTouchListener implements ColumnChartOnValueSelectListener {
@Override
public void onValueSelected(int columnIndex, int subcolumnIndex, SubcolumnValue value) {
SingleToast.showToast(getActivity(), String.valueOf(value.getLabelAsChars()), 2000);
}
@Override
public void onValueDeselected() {
}
}
}
4.4.4 年度收入报表
1.说明:年度收入报表进行了整年收入的整理,还可以进行报表的分享。
2. 年度收入报表效果图如图4.15所示:
图4.15年度收入报表页面
3. 年度收入报表关键代码:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.activity_annotation, container, false);
FontStyle.setDefaultTextSize(DensityUtils.sp2px(getActivity(), 15));
return rootView;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mApp = (GdApp) getActivity().getApplication();
final List<InTableBean> inTableBeans = new ArrayList<>();
for(AccountBean accountBean: mApp.mAccBeanYearColumnList){
if(accountBean.getAccountType().equals(C.COME_TYPE.IN)){
inTableBeans.add(InTableBean.getInTableBean(accountBean));
}
}
table = (SmartTable<InTableBean>) rootView.findViewById(R.id.table);
table.setData(inTableBeans);
table.getConfig().setShowTableTitle(true);
table.getConfig().setShowXSequence(true);
table.getConfig().setShowYSequence(true);
table.setZoom(true, 2, 0.2f);
}
}
4.4.5 年度支出报表
1.说明:将整年支出整理为报表的形式,也可以进行分享。
2.App年度支出报表效果图如图4.16所示:
图4.16 年度支出报表页面
3. 年度支出报表关键代码:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.activity_annotation, container, false);
FontStyle.setDefaultTextSize(DensityUtils.sp2px(getActivity(), 15));
return rootView;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mApp = (GdApp) getActivity().getApplication();
final List<InTableBean> inTableBeans = new ArrayList<>();
for(AccountBean accountBean: mApp.mAccBeanYearColumnList){
if(accountBean.getAccountType().equals(C.COME_TYPE.OUT)){
inTableBeans.add(InTableBean.getInTableBean(accountBean));
}
}
table = (SmartTable<InTableBean>) rootView.findViewById(R.id.table);
table.setData(inTableBeans);
table.getConfig().setShowTableTitle(true);
table.getConfig().setShowXSequence(true);
table.getConfig().setShowYSequence(true);
table.setZoom(true, 2, 0.2f);
}
}
4.5设置管理
4.5.1收入资产设置
1.用户可以通过点击进行收入资产设置,包括工资收入、股票收入或者其他收入。
2. 收入资产设置效果图如下图4.17所示:
图4.17收入资产设置页面
3. 收入资产设置的核心代码:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_somecome, container, false);
initViews();
menuActivity = (TabsActivity) mAct;
return rootView;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
private void initViews() {
initFloatBtn();
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(mAct));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(DividerItemDecoration.VERTICAL);
dividerItemDecoration.setColor(getResources().getColor(R.color.colorPrimary));
dividerItemDecoration.setSize(1);
mRecyclerView.addItemDecoration(dividerItemDecoration);
mSwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipe_container);
mSwipeRefreshLayout.setColorSchemeColors(getResources().getColor(R.color.theme_accent));
doRefresh();
}
private void initFloatBtn() {
mFabActBtn = (FloatingActionButton) rootView.findViewById(R.id.fab_normal);
mFabActBtn.setButtonSize(FloatingActionButton.SIZE_NORMAL);
mFabActBtn.setImageDrawable(new IconicsDrawable(mAct, GoogleMaterial.Icon.gmd_add).color(Color.WHITE).actionBar());
mFabActBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//增加一则
showAdd();
}
});
}
4.5.2支出资产设置
1.说明:用户可以进行相关支出资产的删除和修改。
2. 支出资产设置效果图如下图4.18所示
图4.18 支出资产设置页面
3. 支出资产设置的核心代码:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_somecome, container, false);
initViews();
menuActivity = (TabsActivity) mAct;
return rootView;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
private void initViews() {
initFloatBtn();
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(mAct));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(DividerItemDecoration.VERTICAL);
dividerItemDecoration.setColor(getResources().getColor(R.color.colorPrimary));
dividerItemDecoration.setSize(1);
mRecyclerView.addItemDecoration(dividerItemDecoration);
mSwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipe_container);
mSwipeRefreshLayout.setColorSchemeColors(getResources().getColor(R.color.theme_accent));
4.5.3 预算设置
1.预算设置可以进行日预算、月预算和年预算,进行金额的限制。
2. 预算设置页面效果图如下图4.19所示
图4.19 预算设置页面
3. 预算设置的核心代码:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_limit, container, false);
mEdDay = rootView.findViewById(R.id.ed_day);
mEdMonth = rootView.findViewById(R.id.ed_month);
mEdYear = rootView.findViewById(R.id.ed_year);
mTxUserName = rootView.findViewById(R.id.tx_user);
mBtnSet = rootView.findViewById(R.id.btn_set);
mBtnSet.setOnClickListener(this);
mTxUserName.setText(mApp.getCurrentUser() + "支付限额:");
mEdDay.setText("" + mSelfDayMax);
mEdMonth.setText("" + GdApp.mSelfMonthMax);
mEdYear.setText("" + GdApp.mSelfYearMax);
return rootView;
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_set:
/*
* 源代码
* 输入的仅为int类型,不能输入并保存小数
* */
/*mApp.mSelfDayMax = Integer.parseInt(mEdDay.getEditableText().toString());
mApp.mSelfMonthMax = Integer.parseInt(mEdMonth.getEditableText().toString());
mApp.mSelfYearMax = Integer.parseInt(mEdYear.getEditableText().toString());
DBProvider.getInstance(mAct).updateUserInfo(mApp.getCurrentUser(),mApp.mSelfDayMax,mApp.mSelfMonthMax,mApp.mSelfYearMax);
SingleToast.showToast(mAct,"限额修改成功",2000);
try{
mApp.mSelfDayMax = Float.valueOf(mEdDay.getEditableText().toString());
}catch (NumberFormatException e){
showHint(mAct
.getString(R.string.error_day_max_null));
return;
}
try{
mApp.mSelfMonthMax = Float.valueOf(mEdMonth.getEditableText().toString());
}catch (NumberFormatException e){
showHint(mAct
.getString(R.string.error_month_max_null));
return;
}
try{
mApp.mSelfYearMax = Float.valueOf(mEdYear.getEditableText().toString());
}catch (NumberFormatException e){
showHint(mAct
.getString(R.string.error_year_max_null));
return;
}
if (DBProvider.getInstance(mAct).updateUserInfo(mApp.getCurrentUser(), mSelfDayMax, GdApp.mSelfMonthMax, GdApp.mSelfYearMax)) {
SingleToast.showToast(mAct, "限额修改成功", 2000);
} else {
SingleToast.showToast(mAct, "限额修改失败", 2000);
}
break;
default:
break;
}
}
}
4.5.4账户设置
1.账户设置页面,用户可以进行微信或者支付宝的设置,还可以进行删除或者修改。
2. 账户设置效果图如下图4.20所示
图4.20 账户设置页面
3. 账户设置的关键代码:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_somecome, container, false);
initViews();
menuActivity = (TabsActivity) mAct;
return rootView;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
private void initViews() {
initFloatBtn();
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(mAct));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(DividerItemDecoration.VERTICAL);
dividerItemDecoration.setColor(getResources().getColor(R.color.colorPrimary));
dividerItemDecoration.setSize(1);
mRecyclerView.addItemDecoration(dividerItemDecoration);
mSwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipe_container);
mSwipeRefreshLayout.setColorSchemeColors(getResources().getColor(R.color.theme_accent));
4.5.5提醒设置
1.用户可以设置每天提醒账单的时间,还可以进行提醒设置的取消。
2. 提醒设置效果图如下图4.21所示
图4.21 提醒设置页面
3. 提醒设置的关键代码:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_alarm, container, false);
mTxTime = rootView.findViewById(R.id.tx_alarm_content);
mBtn = rootView.findViewById(R.id.btn_alarm);
mBtnCancel = rootView.findViewById(R.id.btn_alarm_cancel);
String time = (String) SPUtils.getParam(getActivity(), C.SP.ALARM_TIME, "");
if (TextUtils.isEmpty(time)) {
mTxTime.setText("暂未设定");
} else {
mTxTime.setText(time);
}
//实例化闹钟管理器
alarmManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
mBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//获取当前系统的时间
Calendar calendar = Calendar.getInstance();
int x = calendar.get(Calendar.HOUR_OF_DAY);
int f = calendar.get(Calendar.MINUTE);
//01.弹出时间对话框(选择时间)
TimePickerDialog timePickerDialog = new TimePickerDialog(getActivity(), new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker timePicker, int i, int i1) {
//02.确定选择好的时间
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, i);
c.set(Calendar.MINUTE, i1);
//04.时间一到,执行相对应的操作
Intent intent = new Intent();
intent.setAction("com.smile.account.alarm");
pendingIntent = PendingIntent.getBroadcast(getActivity(), 0x102, intent, 0);
//03.设置闹钟(单次)
alarmManager.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pendingIntent);
//03.设置闹钟(周期)
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), 60 * 60 * 24 * 1000, pendingIntent);
String time = i + ":" + i1;
SPUtils.setParam(getActivity(), C.SP.ALARM_TIME, time);
SingleToast.showToast(getContext(), "设置成功!", 2000);
mTxTime.setText(time);
}
}, x, f, true);
timePickerDialog.show();
}
});
//结束周期性闹钟的点击事件
mBtnCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setAction("com.smile.account.alarm");
pendingIntent = PendingIntent.getBroadcast(getActivity(), 0x102, intent, 0);
alarmManager.cancel(pendingIntent);
SPUtils.setParam(getActivity(), C.SP.ALARM_TIME, "");
mTxTime.setText("暂未设定");
SingleToast.showToast(getContext(), "设置成功!", 2000);
}
});
return rootView;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
}
4.5.6关于应用
1.说明:关于应用界面展示相应的软件名称、软件简介等。
2. 关于应用效果图如下图4.22所示
图4.22 关于应用页面
3. 关于应用的关键代码:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_about, container, false);
return rootView;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
}
4.5.7退出应用
1.用户在点击退出应用,点击确定就可以退出软件。
2. 退出应用效果图如下图4.23所示
图4.23退出应用页面
3. 退出应用的关键代码:
public void showExitDialog() {
new MaterialDialog.Builder(this)
.content(R.string.oyt_app_sure)
.positiveText(android.R.string.ok).onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(MaterialDialog dialog, DialogAction which) {
SPUtils.setParam(TabsActivity.this,
C.SP.remember_login, false);
finish();
}
}).negativeText(android.R.string.cancel).show();
}
总结
这学期暂告收尾,这也意味着我在学校这学期的生活既将结束。这学期的收获很多,能在众多学富五车、才华横溢的老师们的熏陶下度过,实是荣幸之极。在这学期时间里,我在学习上和思想上都受益非浅。这除了自身努力外,与各位老师、同学和朋友的关心、支持和鼓励是分不开的。
期末作业设计是我们总结学期的收获、认清自我。同时,还帮助我们改变一些处理事情是懒惰的习惯。从最初的开始搜集资料,整理资料,到方案比选,确定方案,再到着手开始进行项目的分配、功能的实现、界面的布局、前端与后台的连接,软件的测试。没有老师的辛勤栽培,孜孜教诲,就没有我们期末作业设计的顺利完成。通过这段时间的努力,我的毕业设计《基于Android的记账本1设计与实现》终于完成了,这意味着这学期生活即将结束。通过期末作业设计,本人深刻的领会到基础的重要性,期末作业设计不仅仅能帮助学生检查一个学期的学习成果,更多的是期末作业设计可以帮助我们更加清楚的认识自我,磨练学生的意志和耐性,这会是为我日后的学习和生活带来很大的帮助。
最后,感谢老师们的肯定,以及感谢大家这学期对我的帮助,让我们能够顺利的完成期末作业。
附录
名词术语:
JDK Java Development Kit
Android 基于Linux操作系统的手机平台
SDK Android Software Development Kit
ADT Android Development Tool Anroid开发工具
IDE Intergrate Design Environment 集成开发环境
ADB Android Debug Bridge 调试桥
AVD Android Virtual Devices Android虚拟设备
DDMS Dalvik Debug Monitor Service 调试监视服务
xmlns XML NamePace XML命名空间
参考文献
[1]张昊川.基于Android的理财系统APP的设计[D].江西:江西财经大学,2018.
[2]潘彬彬.一指记账APP软件设计[J].大众标准化,2020,(02):56-58.
[3]张晓元.移动互联服务个人理财:一指记账App的需求与实现[J].区域治理,2019, (47):163-166.
[4]刘芳华,余丽萍.基于Android的记账助手APP的设计与实现[J].河南科技,2019,(26):21-23.
[5]欧阳燊.Android Studio开发实战[M].北京:清华大学出版社,2018:12-52.
[6]潘沁园,包玉婷,杜鑫,等.大学生智能消费记账类APP的设计与实现[J].科学技术创新,2020,(15):68-70.
[7]邹达.30天App开发从0到1[M].北京:人民邮电出版社,2018.
[8]董航.基于记账管理APP系统需求分析与设计[J].辽宁高职学报,2020,22(10):88-91+101.
[9]郝哲璞.记账软件对理财的意义——以“一指记账”APP为例[J].投资与合作,2020,(04):124-126.
[10]张俊林,华运.大学生财务管理APP设计与实现[J].电脑知识与技术,2019,15(28):111-113.
[11]李秀红,徐介新,吕兰兰,等.基于Android的大学生掌上理财APP的设计与应用[J].信息技术与信息化,2019,(07):31-33.
[12]邱林,陆迅.O2O校园商城APP平台的设计与开发[J].广西教育,2019,(11):190-192.
[13]吕志远.基于市场调研的在校大学生记账APP设计研究[J].中国管理信息化,2019,22(04):200-201.
[14]张婧云,王佳.基于游戏化思维的记账类APP设计研究——以“记账城市”为例[J].艺术家,2018,(10):53-55.
[15]潘镜如,廖姝涵,林心茹.当今互联网+时代下北海市海产品手机APP界面设计研究[J].风景名胜,2019,(05):2-25.
[16]肖睿,崔雪炜,艾华,等.Java面向对象程序开发及实战[M].北京:人民邮电出版社,201801:209.
点击获取该项目
[猪猪记账本的完整源代码+万字文档论文]