10分钟手把手教你用Android手撸一个简易的个人记账App

简介: 该文章提供了使用Android Studio从零开始创建一个简单的个人记账应用的详细步骤,包括项目搭建、界面设计、数据库处理及各功能模块的实现方法。

封面

⛱️序言

前段时间期末周,这学期有一门课叫移动应用开发,这门课的期末作业是用 Android 写一个个人记账管理系统。 Android 的前台是用 xml 实现,后台是用 java 实现。于是,对这两门语言不太熟悉的周一,开始了漫漫长路的摸索之旅。

接下来就来讲解,如何从0到1实现一个简易的个人记账系统

一起来学习⑧~🙃

温馨小提示: 第二部分的编码阶段代码较多,可直接滑到第三部分看运行效果,并到第四部分克隆github仓库代码,阅读体验更加~

📋一、系统结构设计Design

1. 需求分析

首先我们先来看下老师的需求👇

设计和实现一个类似个人财务管理的 Android APP ,数据库采用 SQLite (也可以直接访问 WebMySQL 数据库、或提供 Web 接口访问 MySQL 数据库)。

APP应具备以下功能:

  • 用户注册和登录(这类 APP 一般面对个人,用户不需要分类别);
  • 收入和支出管理(单条收支记录的添加、删除和修改,收入和支出每一条记录至少包括日期、类型、金额和说明。)
  • 收入和支出查询(根据时间段、类别等进行查询)
  • 收入和支出统计(例如某个月、某个星期或指定时间段的总收支)
  • 其他要求:界面设计应尽量美观,可以添加一些图片或背景。

基于以上需求,周一对所要实现的功能进行了整理。请看下方思维导图:

需求分析

2. 数据库设计

分析完成之后,接下来开始设计数据库详情见下方思维导图:

数据库设计

因为功能较为简单,所以数据库只设计了两张表。

3. 界面设计

设计完数据库之后,开始楷模润色该 APP 的界面。基于本次课题需求,周一设计了5个界面。接下来先来看 App具体界面设计:

界面设计


看完五个界面所需要的内容之后,接下来,我们来对它进行原型绘制。请看下图:

原型图


现在,原型图设计完毕。我们接着设计高保真 App 界面。请看下图:

高保真界面1

高保真界面2

4. 过程设计

好了,看完原型图之后,我们是不是该来想想页面与页面之间,是怎么进行交互的呢?

因此,现在我们来对整个过程进行设计。详情见下方思维导图:

过程设计

📘二、编码阶段Coding

1. 项目结构🗂️

(1)文件目录

先来看项目的文件目录详情看下图👇

项目文件结构

(2)AndroidManifest.xml

接下来附上 AndroidManifest.xml 的代码,具体代码如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.financial.management">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="个人财务管理App"
        android:roundIcon="@mipmap/ic_launcher"
        android:supportsRtl="true"
        android:theme="@style/Theme.Final">
       <activity android:name="com.financial.management.ManageActivity"></activity>
        <activity android:name="com.financial.management.SearchRecordActivity" />
        <activity android:name="com.financial.management.RegisterActivity"/>
        <activity android:name="com.financial.management.UserCenterActivity" />
        <activity android:name="com.financial.management.MainActivity">

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        </activity>
    </application>

</manifest>

(3)Activity类解读

看完上面两个内容之后,接下来是Activity类的解读时间。详情见下表👇

文件名 作用
MainActivity 用户登录页面Activity,用户可以进行登录。
RegisterActivity 用户注册页面Activity,用户可以进行注册。
UserCenterActivity 个人中心Activity,对应用户个人中心的4个按钮进行功能编写,实现用户收支管理、查看收支、收支统计、退出登录四大功能。
ManageActivity 收支管理Activity,对用户的收入和支出进行管理。
SearchRecordActivity 查询收支Activity,通过条件对数据库中的数据进行查询,得出用户想要查询的收支结果。
DBHelper 创建数据库表和数据库数据,同时实现与数据库操作相关的登录和注册方法。
User 用户类Activity,用于获取用户ID以及密码。

(4)XML解读

解读完 Activity 类之后,现在来对 XML 的各个文件进行介绍。详情见下表👇

文件名 作用
activity_main.xml 用户登录页面,用户通过输入账号和密码,进行登录操作。
activity_register.xml 用户注册页面,用户通过输入账号和密码,进行注册操作。
activity_user_center.xml 个人中心页面,当用户登录成功以后,进行个人中心页面。个人中心实现收支管理、查看收支、收支统计、退出登录四大功能。
activity_search_record.xml 通过选择年份月份来进行查询该年该月份的各个收入支出详情,并且计算总金额以及根据类别来计算该类别的总金额。
activity_manage.xml 用户对自己的日常开销进行收支管理,可以进行添加、删除和修改等操作。
record_item_layout.xml 用来存储列表的传输数据

到这里,大家先对待会要编写的 Activity 类和 XML 文件所要展示的功能先进行一番了解。

2. 静态页面⌛

现在,我们到了真正的编码阶段啦!如果是按照我的编码习惯的话,我一般会先把静态页面进行构建,并把一些需要预留的id等等信息给先处理好,方便后面写业务逻辑时可以直接进行绑定。

针对以上6个静态页面,下面将进行代码编写。

(1)用户登录页面activity_main.xml

activity_main.xml 是用户登录页面,当用户通过输入账号和密码时,可以进行登录操作。具体代码如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:gravity="center_horizontal"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/textView1"
            android:layout_width="360dp"
            android:layout_height="360dp"
            android:gravity="center"
            android:background="@drawable/login_logo"
            android:textColor="#fff"
            android:textSize="24dp"
            android:layout_marginTop="-30dp"
            android:layout_marginHorizontal="45dp"/>

        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:gravity="center|center_horizontal"
            android:text="用户登录"
            android:textColor="#5768C5"
            android:textSize="20dp"
            android:layout_marginTop="-60dp"
            />


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:paddingHorizontal="20dp"
            android:paddingVertical="10dp">

            <ImageView
                android:id="@+id/imageView3"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_weight="0"
                app:srcCompat="@drawable/account" />

            <EditText
                android:id="@+id/edt_uid"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:ems="10"
                android:hint="请输入您的用户名"
                android:inputType="textPersonName" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="0"
            android:orientation="horizontal"
            android:paddingHorizontal="20dp"
            android:paddingVertical="10dp">

            <ImageView
                android:id="@+id/imageView4"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_weight="0"
                app:srcCompat="@drawable/password" />

            <EditText
                android:id="@+id/edt_upwd"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:ems="10"
                android:hint="请输入您的密码"
                android:inputType="textPassword" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:gravity="center"
            android:orientation="horizontal"
            android:paddingHorizontal="60dp">

            <Button
                android:id="@+id/btn_login"
                android:layout_width="100dp"
                android:layout_height="60dp"
                android:layout_weight="1"
                android:text="登录"
                android:textSize="18dp"
                app:backgroundTint="#4757AE"
                app:cornerRadius="50dp" />

        </LinearLayout>

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

            <Button
                android:id="@+id/btn_register"
                android:layout_width="match_parent"
                android:layout_height="40dp"
                android:gravity="center"
                android:text="还没有账号?现在注册"
                android:textColor="#888282"
                android:textColorHint="#FFFFFFFF"
                android:backgroundTint="#FFFFFFFF"
                android:color="#FFFFFF"
                />
        </LinearLayout>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="20dp"
            android:background="#FFFFFF"
            android:layout_marginTop="-10dp"/>

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

(2)用户注册页面activity_register.xml

activity_register.xml 是用户注册页面,用户通过输入账号和密码,可以进行注册操作。具体代码如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".RegisterActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:gravity="center"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/textView10"
            android:layout_width="220dp"
            android:layout_height="220dp"
            android:background="@drawable/register_logo"
            android:gravity="center"
            android:textColor="#FFEB3B"
            android:layout_marginBottom="20dp"/>

        <TextView
            android:id="@+id/textView5"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:gravity="center"
            android:text="用户注册"
            android:textColor="#0C6BC2"
            android:textSize="22sp" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:paddingHorizontal="20dp"
            android:layout_marginTop="10dp">

            <TextView
                android:id="@+id/textView7"
                android:layout_width="wrap_content"
                android:layout_height="45dp"
                android:layout_weight="0"
                android:text="账  号:  "
                android:textColor="#0C6BC2"
                android:textSize="22sp" />

            <EditText
                android:id="@+id/edt_rid"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:ems="10"
                android:hint="请输入需要注册的账号"
                android:inputType="textPersonName" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:paddingHorizontal="20dp"
            android:layout_marginVertical="15dp">

            <TextView
                android:id="@+id/textView8"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="0"
                android:text="密  码:  "
                android:textColor="#0C6BC2"
                android:textSize="22sp" />

            <EditText
                android:id="@+id/edt_rpwd"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:ems="10"
                android:hint="请输入密码"
                android:inputType="textPassword" />
        </LinearLayout>

        <Button
            android:id="@+id/btn_registeruser"
            android:layout_width="260dp"
            android:layout_height="60dp"
            android:layout_gravity="center"
            android:layout_marginVertical="20dp"
            android:background="#2D6C2F"
            android:gravity="center"
            android:text="注册"
            android:textSize="22sp"
            app:backgroundTint="#1C8DE6" />

    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

(3)用户个人中心页面activity_user_center.xml

现在,来到了个人中心页面。在个人中心页面当中,将会显示具体的用户名。同时, 有四个按钮入口,分别是:收支管理,查看收支,退出登录和收支统计。来看下具体代码实现:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".UserCenterActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="120dp"
            android:orientation="horizontal"
            android:gravity="center">

            <ImageView
                android:id="@+id/imageView"
                android:layout_width="60dp"
                android:layout_height="60dp"
                app:srcCompat="@drawable/girl"
                android:layout_marginHorizontal="30dp"/>

            <TextView
                android:id="@+id/tv_welcome"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="center|left"
                android:textColor="#4F92CF"
                android:textSize="24sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center_horizontal"
            android:layout_marginTop="40dp">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginHorizontal="20dp"
                android:background="#FFFFFF"
                android:gravity="center_horizontal"
                android:orientation="vertical"
                android:padding="24dp"
                android:elevation="10dp"
                app:cornerRadius="30dp">

                <ImageView
                    android:id="@+id/btn_recordmanage"
                    android:layout_width="60dp"
                    android:layout_height="60dp"
                    app:srcCompat="@drawable/revenue" />

                <TextView
                    android:id="@+id/textView17"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="20dp"
                    android:text="收支管理"
                    android:textColor="#252020"
                    android:textSize="18sp" />
            </LinearLayout>

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:gravity="center_horizontal"
                android:layout_marginHorizontal="20dp"
                android:background="#FFFFFF"
                android:padding="24dp"
                android:elevation="10dp"
                app:cornerRadius="30dp">

                <ImageView
                    android:id="@+id/btn_searchrecord"
                    android:layout_width="60dp"
                    android:layout_height="60dp"
                    app:srcCompat="@drawable/look" />

                <TextView
                    android:id="@+id/textView22"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="查看收支"
                    android:textColor="#FF252020"
                    android:textSize="18sp"
                    android:layout_marginTop="20dp"/>
            </LinearLayout>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center_horizontal"
            android:layout_marginVertical="30dp">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:gravity="center_horizontal"
                android:layout_marginHorizontal="20dp"
                android:background="#FFFFFF"
                android:padding="24dp"
                android:elevation="10dp"
                app:cornerRadius="30dp">

                <ImageView
                    android:id="@+id/btn_exit"
                    android:layout_width="60dp"
                    android:layout_height="60dp"
                    app:srcCompat="@drawable/exit" />

                <TextView
                    android:id="@+id/textView4"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:text="退出登录"
                    android:textColor="#FF252020"
                    android:textSize="18sp"
                    android:layout_marginTop="20dp"/>
            </LinearLayout>

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:gravity="center_horizontal"
                android:layout_marginHorizontal="20dp"
                android:background="#FFFFFF"
                android:padding="24dp"
                android:elevation="10dp"
                app:cornerRadius="30dp">

                <ImageView
                    android:id="@+id/btn_calcmoney"
                    android:layout_width="60dp"
                    android:layout_height="60dp"
                    app:srcCompat="@drawable/statics" />

                <TextView
                    android:id="@+id/textView23"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="收支统计"
                    android:textColor="#FF252020"
                    android:textSize="18sp"
                    android:layout_marginTop="20dp"/>
            </LinearLayout>

        </LinearLayout>

    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

(4)用户搜索记录页面activity_search_record.xml

用户可以通过选择年份月份和筛选类型,点击搜索,来查询该年该月份的各个收入和支出的详情,同时在该时间点和该筛选类型下,点击计算可以对总金额进行计算。下面附上具体代码实现:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context=".SearchRecordActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:gravity="center"
            android:layout_marginTop="50dp"
            android:layout_marginBottom="10dp">

            <ImageView
                android:id="@+id/imageView2"
                android:layout_width="120dp"
                android:layout_height="120dp"
                app:srcCompat="@drawable/income_2" />

            <TextView
                android:id="@+id/textView20"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="我的收支"
                android:textColor="#3F51B5"
                android:textSize="20sp"
                android:layout_marginTop="10dp"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:orientation="horizontal"
            android:gravity="center_vertical"
            android:layout_marginHorizontal="24dp"
            android:layout_marginTop="30dp">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="100dp"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/textView33"
                    android:layout_width="wrap_content"
                    android:layout_height="50dp"
                    android:text="日期  "
                    android:gravity="center_vertical"
                    android:textColor="#111113"
                    android:textSize="18sp" />

                <TextView
                    android:id="@+id/textView34"
                    android:layout_width="wrap_content"
                    android:layout_height="50dp"
                    android:text="类型  "
                    android:gravity="center_vertical"
                    android:textColor="#FF111113"
                    android:textSize="18sp" />
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="100dp"
                android:layout_weight="1"
                android:orientation="vertical">

                <Spinner
                    android:id="@+id/spin_date"
                    android:layout_width="match_parent"
                    android:layout_height="50dp" />

                <Spinner
                    android:id="@+id/spin_type"
                    android:layout_width="match_parent"
                    android:layout_height="50dp"
                    android:layout_weight="1" />
            </LinearLayout>

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="100dp"
                android:orientation="vertical"
                android:gravity="center_vertical">

                <Button
                    android:id="@+id/btn_search"
                    android:layout_width="60dp"
                    android:layout_height="40dp"
                    android:background="#39DC54"
                    android:text="搜索"
                    android:textColor="#FAF9F9"
                    android:textSize="12sp"
                    app:backgroundTint="#5E97DA" />
            </LinearLayout>
        </LinearLayout>

        <ImageView
            android:layout_width="360dp"
            android:layout_height="0.5dp"
            android:background="#D1CDCD"
            android:layout_gravity="center"
            android:paddingHorizontal="24dp"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:layout_marginHorizontal="24dp">

            <TextView
                android:id="@+id/textView32"
                android:layout_width="wrap_content"
                android:layout_height="50dp"
                android:text="总金额  "
                android:gravity="center_vertical"
                android:textColor="#FF111113"
                android:textSize="18sp" />

            <TextView
                android:id="@+id/tv_show"
                android:layout_width="wrap_content"
                android:layout_height="50dp"
                android:layout_weight="1"
                android:textColor="#4CAF65"
                android:textSize="24sp"
                android:gravity="center_vertical"/>

            <Button
                android:id="@+id/btn_calc"
                android:layout_width="60dp"
                android:layout_height="40dp"
                android:gravity="center_vertical"
                android:text="计算"
                android:textColor="#FAF9F9"
                android:textSize="12sp"
                app:backgroundTint="#5E97DA" />
        </LinearLayout>

        <ImageView
            android:layout_width="360dp"
            android:layout_height="0.5dp"
            android:background="#D1CDCD"
            android:layout_gravity="center"
            android:paddingHorizontal="20dp"/>

        <TextView
            android:id="@+id/textView31"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:gravity="center_vertical"
            android:text="查询结果  "
            android:layout_marginTop="20dp"
            android:textColor="#111113"
            android:layout_marginHorizontal="24dp"
            android:textSize="18sp"/>

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

            <TextView
                android:id="@+id/textView29"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="序号"
                android:textColor="#6290c8"
                android:textStyle="bold"
                android:textSize="18sp"
                android:gravity="center_horizontal"/>

            <TextView
                android:id="@+id/textView26"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="日期"
                android:textColor="#6290c8"
                android:textStyle="bold"
                android:textSize="18sp"
                android:gravity="center_horizontal"/>

            <TextView
                android:id="@+id/textView25"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="类型"
                android:textColor="#6290c8"
                android:textStyle="bold"
                android:textSize="18sp"
                android:gravity="center_horizontal"/>

            <TextView
                android:id="@+id/textView27"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="金额"
                android:textColor="#6290c8"
                android:textStyle="bold"
                android:textSize="18sp"
                android:gravity="center_horizontal"/>

            <TextView
                android:id="@+id/textView28"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="说明"
                android:textColor="#6290c8"
                android:textStyle="bold"
                android:textSize="18sp"
                android:gravity="center_horizontal"/>
        </LinearLayout>

        <ListView
            android:id="@+id/searchlistview"
            android:layout_width="match_parent"
            android:layout_height="500dp"
            android:layout_weight="0"
            android:layout_marginHorizontal="20dp"/>
    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

(5)收支管理页面activity_manage.xml

对于收支管理页面来说,用户可以对自己的日常开销进行收支管理,同时也可以进行添加、删除和修改等操作。具体代码如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ManageActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:gravity="center"
            android:orientation="vertical">

            <ImageView
                android:id="@+id/imageView2"
                android:layout_width="150dp"
                android:layout_height="150dp"
                android:layout_marginTop="20dp"
                app:srcCompat="@drawable/income_1" />

            <TextView
                android:id="@+id/textView20"
                android:layout_width="wrap_content"
                android:layout_height="30dp"
                android:text="收支管理"
                android:textColor="#3F51B5"
                android:textSize="20dp" />
        </LinearLayout>


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/textView36"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginHorizontal="20dp"
                android:text="您选择的序号是:"
                android:textColor="#152029"
                android:textSize="18sp"
                android:textStyle="bold" />

            <TextView
                android:id="@+id/tv_test"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="暂未选择"
                android:textColor="#4CAF50"
                android:textSize="18sp" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginHorizontal="20dp"
            android:layout_marginVertical="10dp"
            android:gravity="center"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/textView29"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_weight="1"
                android:text="序号"
                android:textColor="#111819"
                android:textSize="18sp" />

            <TextView
                android:id="@+id/textView26"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="日期"
                android:textColor="#111819"
                android:textSize="18sp" />

            <TextView
                android:id="@+id/textView25"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="类型"
                android:textColor="#111819"
                android:textSize="18sp" />

            <TextView
                android:id="@+id/textView27"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="金额"
                android:textColor="#111819"
                android:textSize="18sp" />

            <TextView
                android:id="@+id/textView28"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="说明"
                android:textColor="#111819"
                android:textSize="18sp" />

        </LinearLayout>

        <ImageView
            android:layout_width="380dp"
            android:layout_height="0.5dp"
            android:background="#D8D3D3"
            android:paddingHorizontal="20dp" />

        <ListView
            android:id="@+id/recordlistview"
            android:layout_width="wrap_content"
            android:layout_height="120dp"
            android:layout_weight="1"></ListView>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginHorizontal="14dp"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/textView18"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="日期: "
                android:textColor="#101112"
                android:textSize="18sp" />

            <EditText
                android:id="@+id/edt_date"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:ems="10"
                android:hint="填写日期,如:202107表示2021年7月"
                android:inputType="textPersonName" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginHorizontal="14dp"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/textView21"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="类型: "
                android:textColor="#101112"
                android:textSize="18sp" />

            <EditText
                android:id="@+id/edt_type"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:ems="10"
                android:hint="类型为收入或支出"
                android:inputType="textPersonName" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginHorizontal="14dp"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/textView30"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="金额: "
                android:textColor="#101112"
                android:textSize="18sp" />

            <EditText
                android:id="@+id/edt_money"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:ems="10"
                android:hint="请输入金额"
                android:inputType="textPersonName" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginHorizontal="14dp"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/tv_state"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="说明: "
                android:textColor="#101112"
                android:textSize="18sp" />

            <EditText
                android:id="@+id/edt_state"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:ems="10"
                android:hint="阐述说明"
                android:inputType="textPersonName" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginVertical="30dp">

            <Button
                android:id="@+id/btn_add"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginHorizontal="10dp"
                android:layout_weight="1"
                android:text="添加"
                app:backgroundTint="#78C6A3" />

            <Button
                android:id="@+id/btn_update"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginHorizontal="10dp"
                android:layout_weight="1"
                android:text="修改"
                app:backgroundTint="#56AB91" />

            <Button
                android:id="@+id/btn_delete"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginHorizontal="10dp"
                android:layout_weight="1"
                android:text="删除"
                app:backgroundTint="#358F80" />
        </LinearLayout>
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

(6)列表数据记录record_item_layout.xml

record_item_layout.xml 主要用途是存储列表的传输数据。具体代码如下:

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

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:layout_marginHorizontal="20dp"
        android:gravity="center_horizontal"
        android:paddingVertical="2dp">

        <TextView
            android:id="@+id/list_id"
            android:layout_width="40dp"
            android:layout_height="24dp"
            android:layout_weight="1"
            android:textSize="18sp"
            android:gravity="center_horizontal" />

        <TextView
            android:id="@+id/list_date"
            android:layout_width="90dp"
            android:layout_height="24dp"
            android:layout_weight="1"
            android:textSize="18sp"
            android:gravity="center_horizontal" />

        <TextView
            android:id="@+id/list_type"
            android:layout_width="70dp"
            android:layout_height="24dp"
            android:layout_weight="1"
            android:textSize="18sp"
            android:gravity="center_horizontal" />

        <TextView
            android:id="@+id/list_money"
            android:layout_width="70dp"
            android:layout_height="24dp"
            android:layout_weight="1"
            android:textSize="18sp"
            android:gravity="center_horizontal" />

        <TextView
            android:id="@+id/list_state"
            android:layout_width="90dp"
            android:layout_height="24dp"
            android:layout_weight="1"
            android:textSize="18sp"
            android:gravity="center_horizontal" />

    </LinearLayout>
</LinearLayout>

3. 逻辑结构💡

写完静态页面之后,接下来我们要对每个页面的逻辑进行编写。现在我们来看一下各个 Activity 类所实现的内容都有些什么呢?

(1)DBHelper类

DBHelper 类用于创建数据库表数据库数据,同时实现与数据库操作相关的登录和注册方法。具体代码实现如下:

package com.financial.management;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DBHelper extends SQLiteOpenHelper {
   
    public static final String DB_NAME = "Test.db";
    public static final String TABLE_NAME = "userinfo";
    public static final String COLUMN_USERID = "uid";
    public static final String COLUMN_USERPWD = "upwd";


    //创建数据库语句
    private static final String CREATE_TABLE = "create table if not exists "
            + TABLE_NAME + "(" + COLUMN_USERID + " text not null primary key,"
            + COLUMN_USERPWD + " text not null)";

    public DBHelper(Context context) {
   
        super(context, DB_NAME, null, 1);
    }

    //创建数据库方法
    @Override
    public void onCreate(SQLiteDatabase db) {
   
        try {
   
            db.execSQL(CREATE_TABLE);
            db.execSQL("insert into " + TABLE_NAME + " values('11','11')");
        } catch (SQLException e) {
   
            e.printStackTrace();
        }

    }

    //重置数据库方法(先删表,再建表)
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
   
        db.execSQL("drop table  if exists " + TABLE_NAME);
        db.execSQL(CREATE_TABLE);
    }

    //登录方法
    public User userlogin(String userId, String userPwd) {
   
        User user = null;
        SQLiteDatabase db = getReadableDatabase();
        Cursor cursor = db.query(TABLE_NAME,
                new String[]{
   COLUMN_USERID, COLUMN_USERPWD},
                COLUMN_USERID + "=? and " + COLUMN_USERPWD + "=?",
                new String[]{
   userId, userPwd},
                null,
                null,
                null);
        if (cursor.getCount() > 0) {
   
            cursor.moveToFirst();
            user = new User();
            user.setUserId(cursor.getString(cursor.getColumnIndex(COLUMN_USERID)));
            user.setUserPwd(cursor.getString(cursor.getColumnIndex(COLUMN_USERPWD)));

        }
        return user;
    }

    //注册方法
    public long registerUser(User user) {
   
        SQLiteDatabase db = getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put(COLUMN_USERID, user.getUserId());
        contentValues.put(COLUMN_USERPWD, user.getUserPwd());
        return db.insert(TABLE_NAME, null, contentValues);

    }
}

(2)MainActivity类

MainActivity 类是用户登录页面的Activity,主要编写用户登录页面的代码逻辑。具体代码实现如下:

package com.financial.management;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.util.ArrayList;


//登录页面逻辑
public class MainActivity extends AppCompatActivity {
   
    EditText edt_id,edt_pwd;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        edt_id = findViewById(R.id.edt_uid);
        edt_pwd =findViewById(R.id.edt_upwd);
        Button btn_login = findViewById(R.id.btn_login);
        //登录按键
        btn_login.setOnClickListener(new View.OnClickListener() {
   
            @Override
            public void onClick(View v) {
   
                try {
   
                    String userId=edt_id.getText().toString();
                    String userPwd=edt_pwd.getText().toString();
                    DBHelper dbuserHelper=new DBHelper(getApplicationContext());
                    User user = dbuserHelper.userlogin(userId,userPwd);

                    //登录成功跳转对应类型界面
                    if(user!=null) {
   
                        Toast.makeText(getApplicationContext(), user.getUserId() + "登录成功", Toast.LENGTH_SHORT).show();
                        Intent intent;
                        ArrayList<User> list = new ArrayList<>();
                        list.add(user);

                        intent = new Intent(getApplicationContext(), UserCenterActivity.class);
                        intent.putParcelableArrayListExtra("LoginUser", list);
                        startActivity(intent);
                    }else{
   
                        Toast.makeText(getApplicationContext(),"登录失败,密码错误或账号不存在!",Toast.LENGTH_SHORT).show();
                    }
                } catch (Exception e) {
   
                    e.printStackTrace();
                    Toast.makeText(getApplicationContext(),"数据库异常",Toast.LENGTH_SHORT).show();
                }
            }
        });
        //注册按键
        Button btn_register=findViewById(R.id.btn_register);
        btn_register.setOnClickListener(new View.OnClickListener() {
   
            @Override
            public void onClick(View v) {
   
                Intent intent=new Intent(getApplicationContext(),RegisterActivity.class);

                startActivity(intent);
            }
        });
    }
}

(3)RegisterActivity类

RegisterActivity 类是用户注册页面的Activity,主要编写用户注册页面的业务逻辑。具体代码实现如下:

package com.financial.management;


import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.util.ArrayList;

//注册页面逻辑
public class RegisterActivity extends AppCompatActivity {
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_register);
        final EditText edt_rid =findViewById(R.id.edt_rid);
        final EditText edt_rpwd =findViewById(R.id.edt_rpwd);
        //注册按键
        Button btn_registerf=findViewById(R.id.btn_registeruser);
        btn_registerf.setOnClickListener(new View.OnClickListener() {
   
            @Override
            public void onClick(View v) {
   
                User user = new User();
                user.setUserId(edt_rid.getText().toString());
                user.setUserPwd(edt_rpwd.getText().toString());

                DBHelper dbUserHelper = new DBHelper(getApplicationContext());
                if (dbUserHelper.registerUser(user) > 0) {
   
                    Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_SHORT).show();
                    Intent intent;
                    ArrayList<User> list = new ArrayList<>();
                    list.add(user);

                    intent = new Intent(getApplicationContext(), MainActivity.class);
                    startActivity(intent);

                }else{
   
                    Toast.makeText(getApplicationContext(), "您已经注册过此账户,请返回登录", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

(4)UserCenterActivity类

UserCenterActivity 类是个人中心页面的Activity,主要编写个人中心各种按钮跳转的业务逻辑。具体代码实现如下:

package com.financial.management;


import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;

//用户个人中心页面逻辑
public class UserCenterActivity extends AppCompatActivity {
   
    ArrayList<User> list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_user_center);

        Intent intent=getIntent();
        list =intent.getParcelableArrayListExtra("LoginUser");
        User user=list.get(0);
        final String username=user.getUserId();
        TextView tv_welcome=findViewById(R.id.tv_welcome);
        tv_welcome.setText("欢迎您 ,用户"+username);

        //收支管理
        ImageView btn_recordmanage =findViewById(R.id.btn_recordmanage);
        btn_recordmanage.setOnClickListener(new View.OnClickListener() {
   
            @Override
            public void onClick(View v) {
   
                Intent intent1=new Intent(getApplicationContext(), ManageActivity.class);
                startActivity(intent1);
            }
        });
        //收支查询
        ImageView btn_searchrecord=findViewById(R.id.btn_searchrecord);
        btn_searchrecord.setOnClickListener(new View.OnClickListener() {
   
            @Override
            public void onClick(View v) {
   
                Intent intent2=new Intent(getApplicationContext(),SearchRecordActivity.class);
                startActivity(intent2);
            }
        });
        //收支统计
        ImageView btn_calcmoney=findViewById(R.id.btn_calcmoney);
        btn_calcmoney.setOnClickListener(new View.OnClickListener() {
   
            @Override
            public void onClick(View v) {
   
                Intent intent3=new Intent(getApplicationContext(),SearchRecordActivity.class);
                startActivity(intent3);
            }
        });
        //退出按键
        ImageView btn_exit=findViewById(R.id.btn_exit);
        btn_exit.setOnClickListener(new View.OnClickListener() {
   
            @Override
            public void onClick(View v) {
   
                AlertDialog dialog = new AlertDialog.Builder(UserCenterActivity.this).setTitle("退出操作")
                        .setMessage("确定退出,不继续玩玩?")
                        .setPositiveButton("确定", new DialogInterface.OnClickListener() {
   
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
   
                                Intent intent=new Intent(getApplicationContext(), MainActivity.class);
                                startActivity(intent);
                            }
                        }).setNegativeButton("继续留下!", new DialogInterface.OnClickListener() {
   
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
   

                            }
                        }).create();
                dialog.show();

            }
        });
    }
}

(5)SearchRecordActivity类

SearchRecordActivity 类是搜索记录页面的Activity,主要编写我的收支页面的业务逻辑。具体代码实现如下:

package com.financial.management;

import androidx.appcompat.app.AppCompatActivity;

import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

//收支记录页面业务逻辑
public class SearchRecordActivity extends AppCompatActivity {
   
    //定义spinner中的数据
    private String[] date_data= {
   "", "202101", "202102", "202103", "202104", "202105","202106","202107","202108","202109","202110","202111","202112"};
    private String[] type_data = {
   "", "收入", "支出"};
    Spinner spin_date, spin_type;
    ListView listView;
    TextView tv_show;
    float sum=0;
    //数据库
    private String selectDate, selectType;
    private static final String DATABASE_NAME = "Test.db";
    private static final String TABLE_NAME = "record";
    private static final String COLUMN_ID = "id";
    private static final String COLUMN_DATE = "date";
    private static final String COLUMN_TYPE = "type";
    private static final String COLUMN_MONEY = "money";
    private static final String COLUMN_STATE = "state";
    private SQLiteDatabase sqLiteDatabase = null;

    private void selectSumMoney() {
   
        //自定义查询的sql语句
        String sql;
        //如果查询时间和查询类型都为空,则查询整个表
        if (TextUtils.isEmpty(selectDate) && TextUtils.isEmpty(selectType)) {
   
            sql = "select * from " + TABLE_NAME;
            //如果有查询时间,没有查询类型,查询指定内容
        } else if (!TextUtils.isEmpty(selectDate) && TextUtils.isEmpty(selectType)) {
   
            sql = "select * from " + TABLE_NAME + " where date='" + selectDate + "'";
            //如果没有查询时间,有查询类型,查询指定内容
        } else if (TextUtils.isEmpty(selectDate) && !TextUtils.isEmpty(selectType)) {
   //如果没有查询时间,有查询类型
            sql = "select * from " + TABLE_NAME + " where type='" + selectType+"'";
        } else {
   //否则,查询条件都不为空,查询指定内容
            sql ="select * from " + TABLE_NAME + " where date='" + selectDate + "' and type='" + selectType+"'";
        }
        Cursor cursor = sqLiteDatabase.rawQuery(sql, null);

        while (cursor.moveToNext()) {
   

            float money = cursor.getFloat(cursor.getColumnIndex(COLUMN_MONEY));
            sum=sum+money;

            //list.add(map);
        }
        String money2=String.valueOf(sum);
        tv_show.setText(money2);
        sum=0;
    }
    //选择数据
    private void selectData() {
   
        //自定义查询的sql语句
        String sql;
        //如果查询时间和查询类型都为空,则查询整个表
        if (TextUtils.isEmpty(selectDate) && TextUtils.isEmpty(selectType)) {
   
            sql = "select * from " + TABLE_NAME;
            //如果有查询时间,没有查询类型,查询指定内容
        } else if (!TextUtils.isEmpty(selectDate) && TextUtils.isEmpty(selectType)) {
   
            sql = "select * from " + TABLE_NAME + " where date='" + selectDate + "'";
            //如果没有查询时间,有查询类型,查询指定内容
        } else if (TextUtils.isEmpty(selectDate) && !TextUtils.isEmpty(selectType)) {
   //如果没有查询时间,有查询类型
            sql = "select * from " + TABLE_NAME + " where type='" + selectType+"'";
        } else {
   //否则,查询条件都不为空,查询指定内容
            sql = "select * from " + TABLE_NAME + " where date='" + selectDate + "' and type='" + selectType+"'";
        }
        //将查询到的数据封装到Cursor
        Cursor cursor = sqLiteDatabase.rawQuery(sql, null);
        ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>();
        if (cursor.getCount() == 0) {
   
            //查无数据则怒不显示列表
            // listView.setVisibility(View.GONE);
            Toast.makeText(getApplicationContext(), "无数据", Toast.LENGTH_SHORT).show();
        } else {
   
            //查有数据则显示列表
            listView.setVisibility(View.VISIBLE);
            while (cursor.moveToNext()) {
   

                int id = cursor.getInt(cursor.getColumnIndex(COLUMN_ID));
                String date = cursor.getString(cursor.getColumnIndex(COLUMN_DATE));
                String type = cursor.getString(cursor.getColumnIndex(COLUMN_TYPE));
                float money = cursor.getFloat(cursor.getColumnIndex(COLUMN_MONEY));
                String state = cursor.getString(cursor.getColumnIndex(COLUMN_STATE));
                Map<String, String> map = new HashMap<String, String>();
                map.put("id", String.valueOf(id));
                map.put("date", date);
                map.put("type", type);
                map.put("money", String.valueOf(money));
                map.put("state", state);
                list.add(map);
            }
            //创建SimpleAdapter
            SimpleAdapter simpleAdapter = new SimpleAdapter(getApplicationContext(),
                    list,
                    R.layout.record_item_layout,
                    new String[]{
   "id", "date", "type", "money", "state"},
                    new int[]{
   R.id.list_id, R.id.list_date, R.id.list_type, R.id.list_money, R.id.list_state});
            listView.setAdapter(simpleAdapter);

        }
    }

    //时间和类别spinner点击事件
    private void initClick() {
   
        //时间事件
        spin_date.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
   
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
   
                selectDate = date_data[position];
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
   
            }
        });
        //类别事件
        spin_type.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
   
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
   
                selectType = type_data[position];
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
   
            }
        });

        findViewById(R.id.btn_search).setOnClickListener(new View.OnClickListener() {
   
            @Override
            public void onClick(View v) {
   
                selectData();
            }
        });
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search_record);
        tv_show=findViewById(R.id.tv_show);
        try {
   
            //打开数据库,如果是第一次会创建该数据库,模式为MODE_PRIVATE
            sqLiteDatabase = openOrCreateDatabase(DATABASE_NAME, MODE_PRIVATE, null);
            //执行创建表的sql语句,虽然每次都调用,但只有首次才创建表

            //执行查询
            listView = findViewById(R.id.searchlistview);//绑定列表
            selectData();
        } catch (SQLException e) {
   
            Toast.makeText(this, "数据库异常!", Toast.LENGTH_LONG).show();
            e.printStackTrace();
        }

        ArrayAdapter<String> adapter = new
                ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, date_data);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spin_date = findViewById(R.id.spin_date);
        spin_date.setAdapter(adapter);

        ArrayAdapter<String> adapter1 = new
                ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, type_data);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spin_type = findViewById(R.id.spin_type);
        spin_type.setAdapter(adapter1);
        initClick();
        Button btn_calc=findViewById(R.id.btn_calc);
        btn_calc.setOnClickListener(new View.OnClickListener() {
   
            @Override
            public void onClick(View v) {
   
                selectSumMoney();

            }
        });
    }
}

(6)ManageActivity类

ManageActivity 类是收支管理页面的Activity,主要编写用户的收入和支出的业务逻辑,实现收支的增删改查具体代码实现如下:

package com.financial.management;

import androidx.appcompat.app.AppCompatActivity;
import android.content.DialogInterface;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AlertDialog;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class ManageActivity extends AppCompatActivity {
   
    private SQLiteDatabase sqLiteDatabase = null;
    private int selectId = -1;
    EditText edt_date, edt_type, edt_money, edt_state;
    TextView tv_test;

    private static final String DATABASE_NAME = "Test.db";
    private static final String TABLE_NAME = "record";
    private static final String COLUMN_ID = "id";
    private static final String COLUMN_DATE = "date";
    private static final String COLUMN_TYPE = "type";
    private static final String COLUMN_MONEY = "money";
    private static final String COLUMN_STATE = "state";

    //创建表
    private static final String CREATE_TABLE = "create table if not exists " + TABLE_NAME
            + "(" + COLUMN_ID + " integer primary key autoincrement," + COLUMN_DATE + " text," + COLUMN_TYPE
            + " text," + COLUMN_MONEY + " float," + COLUMN_STATE + " text)";

    //自定义的查询方法
    private void selectData() {
   
        //遍历整个表
        String sql = "select * from " + TABLE_NAME ;
        //把查询数据封装到Cursor
        Cursor cursor = sqLiteDatabase.rawQuery(sql, null);
        ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>();
        //用while循环遍历Cursor,再把它分别放到map中,最后统一存入list中,便于调用
        while (cursor.moveToNext()) {
   

            int id = cursor.getInt(cursor.getColumnIndex(COLUMN_ID));
            String date = cursor.getString(cursor.getColumnIndex(COLUMN_DATE));
            String type = cursor.getString(cursor.getColumnIndex(COLUMN_TYPE));
            float money = cursor.getFloat(cursor.getColumnIndex(COLUMN_MONEY));
            String state = cursor.getString(cursor.getColumnIndex(COLUMN_STATE));

            Map<String, String> map = new HashMap<String, String>();
            map.put("id", String.valueOf(id));
            map.put("date", date);
            map.put("type", type);
            map.put("money", String.valueOf(money));
            map.put("state", state);
            list.add(map);
        }

        //创建SimpleAdapter
        SimpleAdapter simpleAdapter = new SimpleAdapter(getApplicationContext(),
                list,
                R.layout.record_item_layout,
                new String[]{
   "id", "date", "type", "money", "state"},
                new int[]{
   R.id.list_id, R.id.list_date, R.id.list_type, R.id.list_money, R.id.list_state});
        final ListView listView = findViewById(R.id.recordlistview);
        //绑定适配器
        listView.setAdapter(simpleAdapter);
        //设置ListView单击事件
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
   
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
   
                ListView tempList = (ListView) parent;


                View mView = tempList.getChildAt(position);
                TextView list_id = mView.findViewById(R.id.list_id);
                TextView list_date = mView.findViewById(R.id.list_date);
                TextView list_type = mView.findViewById(R.id.list_type);
                TextView list_money = mView.findViewById(R.id.list_money);
                TextView list_state = mView.findViewById(R.id.list_state);

                String rid = list_id.getText().toString();
                String date = list_date.getText().toString();
                String type = list_type.getText().toString();
                String money = list_money.getText().toString();
                String state = list_state.getText().toString();

                tv_test.setText(rid);
                edt_date.setText(date);
                edt_type.setText(type);
                edt_money.setText(money);
                edt_state.setText(state);
                selectId = Integer.parseInt(rid);
            }
        });
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_manage);
        try {
   
            sqLiteDatabase = openOrCreateDatabase(DATABASE_NAME, MODE_PRIVATE, null);
            sqLiteDatabase.execSQL(CREATE_TABLE);
            //执行查询
            selectData();
        } catch (SQLException e) {
   
            Toast.makeText(this, "数据库异常!", Toast.LENGTH_LONG).show();
            e.printStackTrace();
        }
        tv_test = findViewById(R.id.tv_test);
        edt_date = findViewById(R.id.edt_date);
        edt_type = findViewById(R.id.edt_type);
        edt_money = findViewById(R.id.edt_money);
        edt_state = findViewById(R.id.edt_state);

        //新增按键
        Button btn_add = findViewById(R.id.btn_add);
        btn_add.setOnClickListener(new View.OnClickListener() {
   
            @Override
            public void onClick(View v) {
   
                if (edt_date.getText().toString().equals("") | edt_type.getText().toString().equals("") | edt_money.getText().toString().equals("") | edt_state.getText().toString().equals("")) {
   
                    Toast.makeText(ManageActivity.this, "数据不能为空!", Toast.LENGTH_LONG).show();
                    return;
                }

                String date = edt_date.getText().toString();
                String type = edt_type.getText().toString();
                String money = edt_money.getText().toString();
                String state = edt_state.getText().toString();
                //定义添加数据的sql语句
                String sql = "insert into " + TABLE_NAME + "(" + COLUMN_DATE + "," + COLUMN_TYPE + "," + COLUMN_MONEY + "," + COLUMN_STATE + ") " +
                        "values('" + date + "','" + type + "','" + money + "','" + state + "')";
                //执行sql语句
                sqLiteDatabase.execSQL(sql);
                Toast.makeText(getApplicationContext(), "新增数据成功!", Toast.LENGTH_LONG).show();
                //刷新显示列表
                selectData();

                //消除数据
                tv_test.setText("");
                edt_date.setText("");
                edt_type.setText("");
                edt_money.setText("");
                edt_state.setText("");
            }
        });

        //修改按键
        Button btn_update = findViewById(R.id.btn_update);
        btn_update.setOnClickListener(new View.OnClickListener() {
   
            @Override
            public void onClick(View v) {
   
                //无选择提示
                if (selectId == -1) {
   
                    Toast.makeText(getApplicationContext(), "请选择要修改的行!", Toast.LENGTH_LONG).show();
                    return;
                }
                //判断是否有空数据
                if (edt_date.getText().toString().equals("") | edt_type.getText().toString().equals("") | edt_money.getText().toString().equals("") | edt_state.getText().toString().equals("")) {
   
                    Toast.makeText(getApplicationContext(), "数据不能为空!", Toast.LENGTH_LONG).show();
                    return;
                }

                String date = edt_date.getText().toString();
                String type = edt_type.getText().toString();
                String money = edt_money.getText().toString();
                String state = edt_state.getText().toString();
                //定义修改数据的sql语句
                String sql = "update " + TABLE_NAME + " set " + COLUMN_DATE + "='" + date + "',type='" + type + "',money='" + money + "',state='" + state + "' where id=" + selectId;
                //执行sql语句
                sqLiteDatabase.execSQL(sql);
                Toast.makeText(getApplicationContext(), "修改数据成功!", Toast.LENGTH_LONG).show();
                //刷新显示列表
                selectData();
                selectId = -1;
                //消除数据
                tv_test.setText("");
                edt_date.setText("");
                edt_type.setText("");
                edt_money.setText("");
                edt_state.setText("");
            }
        });
        //删除按键
        Button btn_delete = findViewById(R.id.btn_delete);
        btn_delete.setOnClickListener(new View.OnClickListener() {
   
            @Override
            public void onClick(View v) {
   
                //无选择提示
                if (selectId == -1) {
   
                    Toast.makeText(ManageActivity.this, "请选择要删除的行!", Toast.LENGTH_LONG).show();
                    return;
                }

                //定义删除对话框
                AlertDialog dialog = new AlertDialog.Builder(ManageActivity.this).setTitle("删除操作")
                        .setMessage("确定删除?此操作不可逆,请慎重选择!")
                        .setPositiveButton("确定", new DialogInterface.OnClickListener() {
   
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
   
                                //定义删除的sql语句
                                String sql = "delete from " + TABLE_NAME + " where id=" + selectId;
                                //执行sql语句
                                sqLiteDatabase.execSQL(sql);
                                //刷新显示列表
                                Toast.makeText(getApplicationContext(), "删除数据成功!", Toast.LENGTH_LONG).show();
                                selectData();
                                selectId = -1;
                                //清除数据
                                tv_test.setText("");
                                edt_date.setText("");
                                edt_type.setText("");
                                edt_money.setText("");
                                edt_state.setText("");
                            }
                        }).setNegativeButton("取消", new DialogInterface.OnClickListener() {
   
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
   

                            }
                        }).create();
                dialog.show();
            }
        });
    }
}

(7)User类

User 类是用户类Activity,用于获取用户ID以及密码。具体代码实现如下:

package com.financial.management;
import android.os.Parcel;
import android.os.Parcelable;

public class User implements Parcelable {
   
    private String userId="";
    private String userPwd="";
    public String getUserId() {
   
        return userId;
    }

    public void setUserId(String userId) {
   
        this.userId = userId;
    }

    public String getUserPwd() {
   
        return userPwd;
    }

    public void setUserPwd(String userPwd) {
   
        this.userPwd = userPwd;
    }



    @Override
    public int describeContents() {
   
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
   
        dest.writeString(this.userId);
        dest.writeString(this.userPwd);
    }

    public User() {
   
    }

    protected User(Parcel in) {
   
        this.userId = in.readString();
        this.userPwd = in.readString();
    }

    public static final Creator<User> CREATOR = new Creator<User>() {
   
        @Override
        public User createFromParcel(Parcel source) {
   
            return new User(source);
        }

        @Override
        public User[] newArray(int size) {
   
            return new User[size];
        }
    };
}

🎵三、运行结果Result

到这里,整个系统的设计就差不多要结束啦!现在我们用一段视频来演示整个系统的运行效果🌈

📈四、结束语

在拿到这个课题呢,周一首先对课题进行了系统结构设计,结构设计完成之后就到了编码阶段。编码阶段分为两部分进行,先是进行静态页面的楷模,而后到了业务逻辑的编写。

讲到这里,整个系统从设计阶段到编码阶段的整个过程讲解就结束啦!这也算是我学习Android的第一个小作品,作品不完美之处较多,后续还将会继续改进~

本文代码已上传至github,戳此链接可下载代码~

🐣彩蛋 One More Thing

(:不合理设计

  • 年月份数据写的太固定了,没有可扩展性
  • 日期应该用日期选择器来做,而不应该是以文本的形式
  • 收入和支出应该以单选框来进行选择,而不应该是文本的形式
  • ……

(:番外篇

  • 关注公众号星期一研究室,第一时间关注学习干货,更多精选专栏待你解锁~
  • 如果这篇文章对你有用,记得留个脚印jio再走哦~
  • 以上就是本文的全部内容!我们下期见!👋👋👋
相关文章
|
10天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
6天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2506 14
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
6天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1519 14
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
|
8天前
|
编解码 JSON 自然语言处理
通义千问重磅开源Qwen2.5,性能超越Llama
击败Meta,阿里Qwen2.5再登全球开源大模型王座
531 13
|
1月前
|
运维 Cloud Native Devops
一线实战:运维人少,我们从 0 到 1 实践 DevOps 和云原生
上海经证科技有限公司为有效推进软件项目管理和开发工作,选择了阿里云云效作为 DevOps 解决方案。通过云效,实现了从 0 开始,到现在近百个微服务、数百条流水线与应用交付的全面覆盖,有效支撑了敏捷开发流程。
19282 30
|
1月前
|
人工智能 自然语言处理 搜索推荐
阿里云Elasticsearch AI搜索实践
本文介绍了阿里云 Elasticsearch 在AI 搜索方面的技术实践与探索。
18836 20
|
1月前
|
Rust Apache 对象存储
Apache Paimon V0.9最新进展
Apache Paimon V0.9 版本即将发布,此版本带来了多项新特性并解决了关键挑战。Paimon自2022年从Flink社区诞生以来迅速成长,已成为Apache顶级项目,并广泛应用于阿里集团内外的多家企业。
17524 13
Apache Paimon V0.9最新进展
|
8天前
|
人工智能 自动驾驶 机器人
吴泳铭:AI最大的想象力不在手机屏幕,而是改变物理世界
过去22个月,AI发展速度超过任何历史时期,但我们依然还处于AGI变革的早期。生成式AI最大的想象力,绝不是在手机屏幕上做一两个新的超级app,而是接管数字世界,改变物理世界。
458 48
吴泳铭:AI最大的想象力不在手机屏幕,而是改变物理世界
|
1天前
|
云安全 存储 运维
叮咚!您有一份六大必做安全操作清单,请查收
云安全态势管理(CSPM)开启免费试用
355 4
叮咚!您有一份六大必做安全操作清单,请查收
|
2天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。