4.18基于Android的个人理财APP

发布时间:2025-09-24 08:31

理财APP如宜人贷提供个人贷款理财 #生活常识# #理财规划建议# #金融资讯平台#

系统的需求分析

1.1系统目标

​财务管理​:为用户提供一个简单易用的个人财务管理工具,帮助用户记录日常收支情况

​预算控制​:允许用户设置月度预算,实时监控预算执行情况,避免超支

​数据分析​:通过图表和报表形式直观展示用户的收支情况,帮助用户了解消费习惯

​历史查询​:提供灵活的查询功能,可按时间范围检索历史交易记录

​移动便捷​:基于Android平台开发,随时随地记录和查看财务数据

1.2功能需求

该理财软件应该具有以下功能:

预算管理:用户可以设置每月预算,并查看当前预算使用情况

收支记录:记录收入与支出,包括金额、类别、日期等信息

流水查询:按日期范围查询收支记录

   图表分析:以柱状图展示每月收支对比

系统的概要设计

该软件是一款是基于Android开发的手机应用,简单实用,易于上手。

2.1 运行环境

1.Android手机或平板电脑:主频在1Ghz及以上,内存为512MB以上,系统版本为Android4.4.2及以上。

2.在eclipse平台下安装了安卓android SDK 插件的电脑:Window All

2.2 数据库表设计

用户表(users)

字段名

类型

约束

说明

user_id

INTEGER

PRIMARY KEY AUTOINCREMENT

用户ID,自增主键

username

TEXT

NOT NULL UNIQUE

用户名,唯一

password

TEXT

NOT NULL

密码(应加密存储)

email

TEXT

电子邮箱

created_at

TEXT

DEFAULT CURRENT_TIMESTAMP

账户创建时间

类别表(categories)

字段名

类型

约束

说明

category_id

INTEGER

PRIMARY KEY AUTOINCREMENT

类别ID,自增主键

name

TEXT

NOT NULL UNIQUE

类别名称

type

INTEGER

NOT NULL CHECK (type IN (1, 2))

1=收入类别,2=支出类别

预算表(budgets)

类型

约束

说明

 

budget_id

INTEGER

PRIMARY KEY AUTOINCREMENT

预算ID,自增主键

user_id

INTEGER

NOT NULL, FOREIGN KEY

关联用户ID

month

TEXT

NOT NULL CHECK (month GLOB '????-??')

预算月份(YYYY-MM格式)

amount

REAL

NOT NULL CHECK (amount > 0)

预算金额(必须大于0)

收入表(incomes)

字段名

类型

约束

说明

income_id

INTEGER

PRIMARY KEY AUTOINCREMENT

收入ID,自增主键

user_id

INTEGER

NOT NULL, FOREIGN KEY

关联用户ID

amount

REAL

NOT NULL CHECK (amount > 0)

收入金额(必须大于0)

category

TEXT

NOT NULL, FOREIGN KEY

收入类别(关联categories表)

description

TEXT

收入描述

date

TEXT

NOT NULL CHECK (date GLOB '????-??-??')

收入日期(YYYY-MM-DD格式)

支出表(expenses)

字段名

类型

约束

说明

expense_id

INTEGER

PRIMARY KEY AUTOINCREMENT

支出ID,自增主键

user_id

INTEGER

NOT NULL, FOREIGN KEY

关联用户ID

amount

REAL

NOT NULL CHECK (amount > 0)

支出金额(必须大于0)

category

TEXT

NOT NULL, FOREIGN KEY

支出类别(关联categories表)

description

TEXT

支出描述

date

TEXT

NOT NULL CHECK (date GLOB '????-??-??')

支出日期(YYYY-MM-DD格式)

created_at

TEXT

DEFAULT CURRENT_TIMESTAMP

记录创建时间

设计与实现部分

运行画面截图

关键代码:

public class MainActivity extends AppCompatActivity {

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        // 初始化按钮

        Button btnBudget = findViewById(R.id.btnBudget);

        Button btnIncome = findViewById(R.id.btnIncome);

        Button btnExpense = findViewById(R.id.btnExpense);

        Button btnReport = findViewById(R.id.btnReport);

        Button btnChart = findViewById(R.id.btnChart);

        Button btnAbout = findViewById(R.id.btnAbout);

        // 设置按钮点击事件

        btnBudget.setOnClickListener(v -> startActivity(new Intent(this, BudgetActivity.class)));

        btnIncome.setOnClickListener(v -> startActivity(new Intent(this, IncomeActivity.class)));

        btnExpense.setOnClickListener(v -> startActivity(new Intent(this, ExpenseActivity.class)));

        btnReport.setOnClickListener(v -> startActivity(new Intent(this, ReportActivity.class)));

        btnChart.setOnClickListener(v -> startActivity(new Intent(this, ChartActivity.class)));

        btnAbout.setOnClickListener(v -> startActivity(new Intent(this, AboutActivity.class)));

    }

}

运行画面截图

关键代码:

public class ChartActivity extends AppCompatActivity {

    private BarChart chart;

    private DatabaseHelper dbHelper;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_chart);

        chart = findViewById(R.id.chart);

        dbHelper = new DatabaseHelper(this);

        setupChart();

        loadChartData(2023); // 默认加载2023年数据

    }

    private void setupChart() {

        chart.getDescription().setEnabled(false);

        chart.setDrawGridBackground(false);

        XAxis xAxis = chart.getXAxis();

        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);

        xAxis.setDrawGridLines(false);

        xAxis.setGranularity(1f);

        xAxis.setLabelCount(12);

        YAxis leftAxis = chart.getAxisLeft();

        leftAxis.setDrawGridLines(true);

        chart.getAxisRight().setEnabled(false);

        chart.getLegend().setEnabled(true);

    }

    private void loadChartData(int year) {

        Map<String, List<Double>> data = dbHelper.getMonthlySummary(year);

        if (data == null || data.isEmpty()) {

            chart.clear();

            chart.setNoDataText("暂无数据");

            return;

        }

        List<BarEntry> incomeEntries = new ArrayList<>();

        List<BarEntry> expenseEntries = new ArrayList<>();

        for (int i = 0; i < 12; i++) {

            incomeEntries.add(new BarEntry(i, data.get("income").get(i).floatValue()));

            expenseEntries.add(new BarEntry(i, data.get("expense").get(i).floatValue()));

        }

        BarDataSet incomeSet = new BarDataSet(incomeEntries, "收入");

        incomeSet.setColor(Color.GREEN);

        BarDataSet expenseSet = new BarDataSet(expenseEntries, "支出");

        expenseSet.setColor(Color.RED);

        BarData barData = new BarData(incomeSet, expenseSet);

        barData.setBarWidth(0.4f);

        chart.setData(barData);

        chart.invalidate();

    }

}

运行画面截图

关键代码:

package com.example.personalfinance;

import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class BudgetActivity extends AppCompatActivity {
    private EditText etAmount;
    private DatabaseHelper dbHelper;

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

        dbHelper = new DatabaseHelper(this);
        etAmount = findViewById(R.id.etAmount);
        Button btnSave = findViewById(R.id.btnSave);

        // 获取当前年月
        String currentMonth = new SimpleDateFormat("yyyy-MM", Locale.getDefault()).format(new Date());

        // 显示当前预算
        double budget = dbHelper.getBudgetByMonth(currentMonth);
        if (budget > 0) {
            etAmount.setText(String.valueOf(budget));
        }

        btnSave.setOnClickListener(v -> {
            String amountStr = etAmount.getText().toString().trim();
            if (amountStr.isEmpty()) {
                Toast.makeText(this, "请输入预算金额", Toast.LENGTH_SHORT).show();
                return;
            }

            double amount = Double.parseDouble(amountStr);
            if (amount <= 0) {
                Toast.makeText(this, "预算金额必须大于0", Toast.LENGTH_SHORT).show();
                return;
            }

            if (dbHelper.addBudget(currentMonth, amount)) {
                Toast.makeText(this, "预算设置成功", Toast.LENGTH_SHORT).show();
                finish();
            } else {
                Toast.makeText(this, "预算设置失败", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

运行画面截图

关键代码:

package com.example.personalfinance;

import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class IncomeActivity extends AppCompatActivity {
    private EditText etAmount, etDescription;
    private Spinner spCategory;
    private DatabaseHelper dbHelper;

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

        dbHelper = new DatabaseHelper(this);
        etAmount = findViewById(R.id.etAmount);
        etDescription = findViewById(R.id.etDescription);
        spCategory = findViewById(R.id.spCategory);
        Button btnSave = findViewById(R.id.btnSave);

        // 设置收入类别下拉列表
        String[] categories = {"工资", "奖金", "投资", "兼职", "其他"};
        ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, categories);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spCategory.setAdapter(adapter);

        btnSave.setOnClickListener(v -> {
            String amountStr = etAmount.getText().toString().trim();
            String description = etDescription.getText().toString().trim();
            String category = spCategory.getSelectedItem().toString();

            if (amountStr.isEmpty()) {
                Toast.makeText(this, "请输入收入金额", Toast.LENGTH_SHORT).show();
                return;
            }

            double amount = Double.parseDouble(amountStr);
            if (amount <= 0) {
                Toast.makeText(this, "收入金额必须大于0", Toast.LENGTH_SHORT).show();
                return;
            }

            // 获取当前日期
            String currentDate = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date());

            if (dbHelper.addIncome(amount, category, description, currentDate)) {
                Toast.makeText(this, "收入记录成功", Toast.LENGTH_SHORT).show();
                finish();
            } else {
                Toast.makeText(this, "收入记录失败", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

运行画面截图

关键代码:

package com.example.personalfinance;

import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class ExpenseActivity extends AppCompatActivity {
    private EditText etAmount, etDescription;
    private Spinner spCategory;
    private DatabaseHelper dbHelper;

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

        dbHelper = new DatabaseHelper(this);
        etAmount = findViewById(R.id.etAmount);
        etDescription = findViewById(R.id.etDescription);
        spCategory = findViewById(R.id.spCategory);
        Button btnSave = findViewById(R.id.btnSave);

        // 设置支出类别下拉列表
        String[] categories = {"餐饮", "交通", "购物", "娱乐", "住房", "医疗", "教育", "其他"};
        ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, categories);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spCategory.setAdapter(adapter);

        btnSave.setOnClickListener(v -> {
            String amountStr = etAmount.getText().toString().trim();
            String description = etDescription.getText().toString().trim();
            String category = spCategory.getSelectedItem().toString();

            if (amountStr.isEmpty()) {
                Toast.makeText(this, "请输入支出金额", Toast.LENGTH_SHORT).show();
                return;
            }

            double amount = Double.parseDouble(amountStr);
            if (amount <= 0) {
                Toast.makeText(this, "支出金额必须大于0", Toast.LENGTH_SHORT).show();
                return;
            }

            // 获取当前日期
            String currentDate = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date());

            if (dbHelper.addExpense(amount, category, description, currentDate)) {
                Toast.makeText(this, "支出记录成功", Toast.LENGTH_SHORT).show();
                finish();
            } else {
                Toast.makeText(this, "支出记录失败", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

运行画面截图

关键代码:

package com.example.personalfinance;

import android.app.DatePickerDialog;
import android.os.Bundle;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import android.widget.Toast;

public class ReportActivity extends AppCompatActivity {
    private EditText etStartDate, etEndDate;
    private Button btnQuery;
    private ListView lvTransactions;
    private TextView tvTotalIncome, tvTotalExpense;
    private DatabaseHelper dbHelper;
    private Calendar calendar = Calendar.getInstance();
    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());

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

        dbHelper = new DatabaseHelper(this);
        etStartDate = findViewById(R.id.etStartDate);
        etEndDate = findViewById(R.id.etEndDate);
        btnQuery = findViewById(R.id.btnQuery);
        lvTransactions = findViewById(R.id.lvTransactions);
        tvTotalIncome = findViewById(R.id.tvTotalIncome);
        tvTotalExpense = findViewById(R.id.tvTotalExpense);

        // 设置默认日期范围(本月)
        String firstDay = new SimpleDateFormat("yyyy-MM-01", Locale.getDefault()).format(calendar.getTime());
        String today = dateFormat.format(calendar.getTime());
        etStartDate.setText(firstDay);
        etEndDate.setText(today);

        // 设置日期选择器
        etStartDate.setOnClickListener(v -> showDatePickerDialog(etStartDate));
        etEndDate.setOnClickListener(v -> showDatePickerDialog(etEndDate));

        // 查询按钮点击事件
        btnQuery.setOnClickListener(v -> {
            String startDate = etStartDate.getText().toString().trim();
            String endDate = etEndDate.getText().toString().trim();

            if (startDate.isEmpty() || endDate.isEmpty()) {
                Toast.makeText(this, "请选择日期范围", Toast.LENGTH_SHORT).show();
                return;
            }

            // 查询收入
            List<Transaction> incomes = dbHelper.getIncomesByDateRange(startDate, endDate);
            double totalIncome = 0;
            for (Transaction income : incomes) {
                totalIncome += income.getAmount();
            }

            // 查询支出
            List<Transaction> expenses = dbHelper.getExpensesByDateRange(startDate, endDate);
            double totalExpense = 0;
            for (Transaction expense : expenses) {
                totalExpense += expense.getAmount();
            }

            // 显示总计
            tvTotalIncome.setText(String.format(Locale.getDefault(), "总收入: %.2f", totalIncome));
            tvTotalExpense.setText(String.format(Locale.getDefault(), "总支出: %.2f", totalExpense));

            // 合并收支记录并排序
            incomes.addAll(expenses);
            incomes.sort((t1, t2) -> t2.getDate().compareTo(t1.getDate()));

            // 显示流水列表
            TransactionAdapter adapter = new TransactionAdapter(this, incomes);
            lvTransactions.setAdapter(adapter);
        });
    }

    private void showDatePickerDialog(final EditText editText) {
        DatePickerDialog datePickerDialog = new DatePickerDialog(
                this,
                (view, year, month, dayOfMonth) -> {
                    calendar.set(year, month, dayOfMonth);
                    editText.setText(dateFormat.format(calendar.getTime()));
                },
                calendar.get(Calendar.YEAR),
                calendar.get(Calendar.MONTH),
                calendar.get(Calendar.DAY_OF_MONTH)
        );
        datePickerDialog.show();
    }
}

运行画面截图:

关键代码:

package com.example.personalfinance;

import android.os.Bundle;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

public class AboutActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_about);

        TextView tvVersion = findViewById(R.id.tvVersion);
        tvVersion.setText("版本: 1.0.0");

        TextView tvDescription = findViewById(R.id.tvDescription);
        tvDescription.setText("个人理财应用\n\n功能包括:\n- 预算管理\n- 收入记录\n- 支出记录\n- 流水查询\n- 图表分析\n\n©2025 个人理财团队");
    }
}

心得体会

​问题1​:图表无法显示数据

​解决​:检查数据库查询逻辑,确保返回正确的数据格式。

​问题2​:按钮点击无响应

​解决​:检查activity_main.xml中的id是否与代码匹配

网址:4.18基于Android的个人理财APP https://www.yuejiaxmz.com/news/view/1330049

相关内容

基于Android的家庭理财APP的设计与实现(论文+源码)
基于Android的个人助理APP设计与实现毕业论文
基于Android平台下的健康管理APP/基于android的健康管理系统
基于 Android 的个人健康管理 APP 设计与实现
android 个人理财系统,基于Android的个人理财助手的设计与实现
基于Android的家庭理财系统的设计与实现
基于Android实现个人理财APP的设计与实现演示【附项目源码+论文说明】
android基于饮食健康管理app
基于android个人生活助手app
湖南科技大学Android课程设计之个人理财小助手APP

随便看看