news 2026/9/10 4:47:59

Android本地理财App开发:SQLite+MPAndroidChart实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Android本地理财App开发:SQLite+MPAndroidChart实战指南

简介:本资源是一份面向Android开发初学者与课程设计实践者的完整个人理财App项目,适用于高校移动应用开发实训、Java安卓课程设计及毕业设计参考。项目采用Java语言开发,基于Android原生框架实现收入统计、支出统计、理财分析、备忘录等核心功能,具备清晰的业务逻辑与可运行的UI交互体验。压缩包共1384个文件,包含136个Java源码文件、145个XML布局与配置文件、247个DEX字节码及245个CLASS类文件,辅以JSON数据配置、PNG图标资源、MP3提示音及演示MP4视频,整体大小为29.75MB,结构完整、模块分明,便于理解Android项目构建流程与MVC分层设计。目前已有174人学习下载,资源提供可直接导入Android Studio运行的源码工程、配套演示视频及基础项目文档,是掌握安卓基础组件、SQLite本地存储与Activity生命周期管理的优质实战范例。

1. 一个能跑在真机上的个人理财App,为什么比“Hello World”更值得课程设计选题?

很多同学做安卓课程设计时,第一反应是写个计算器、记事本或天气预报——功能简单、资料多、容易交差。但真正拉开差距的,其实是那种「看起来日常、做起来有层次」的项目。这个基于 Android 的个人理财 App 就是典型:它不依赖后端服务器,纯本地 SQLite 存储;收入/支出分类用枚举+图标映射,不是硬编码字符串;统计图表用 MPAndroidChart 实现柱状图与饼图联动;备忘录支持富文本格式(含日期高亮与关键词标记)。更重要的是,它完整覆盖了 Android 开发中五个关键断层:Activity 生命周期管理(如退出时保存未提交表单)、RecyclerView 多类型 Item 布局(收支列表 vs 统计卡片)、SQLite 数据库事务封装(新增一笔支出需同步更新总余额与分类汇总)、Fragment 状态持久化(切换 Tab 不重绘图表)、以及 Material Design 组件的实际落地(BottomNavigationView + AppBarLayout 滚动联动)。适合大三下学期到大四上学期、已完成《移动应用开发》基础课、正准备实习面试或毕业设计开题的学生——你不仅能把它当作业交,还能拆出 3 个可复用模块放进简历项目栏。

2. 从源码结构到核心模块:Java+Android 架构如何支撑理财逻辑闭环

这个项目采用经典的分层架构,但不是教科书式的 MVP 或 MVVM,而是针对课程设计场景做了轻量裁剪:com.example.finance包下直接划分为model(实体类与 DAO 接口)、database(SQLiteOpenHelper 封装与事务工具类)、ui(Activity/Fragment 及 Adapter)、util(日期格式化、金额单位转换、图表数据生成器)。这种结构没有过度抽象,却把数据流控制得非常清晰——所有业务逻辑都在 Activity 中触发,DAO 层只负责 CRUD,View 层不持有任何 Model 引用。下面以「添加一笔支出」为例,说明三层如何协作。

2.1 数据模型定义与 SQLite 表结构设计

项目使用Expense.javaIncome.java分别表示支出与收入实体,二者继承自基类Transaction,共享id,amount,date,category,note字段。关键点在于category字段并非 String 类型,而是int类型的枚举索引:

public class Transaction { public static final int CATEGORY_FOOD = 0; public static final int CATEGORY_TRANSPORT = 1; public static final int CATEGORY_SHOPPING = 2; // ... 其他分类 private int category; // 存储整数索引,非字符串 }

对应 SQLite 建表语句在FinanceDatabaseHelper.java中定义:

CREATE TABLE IF NOT EXISTS expense ( id INTEGER PRIMARY KEY AUTOINCREMENT, amount REAL NOT NULL, date TEXT NOT NULL, -- 格式为 yyyy-MM-dd category INTEGER NOT NULL, -- 对应上述枚举值 note TEXT );

提示:用整数代替字符串存储分类,既节省空间又避免拼写错误导致查询失败。后续在 UI 层通过getCategoryName(int category)方法动态映射为中文名,解耦数据存储与显示逻辑。

2.2 数据库操作封装:事务安全与批量插入优化

FinanceDatabaseHelper继承自SQLiteOpenHelper,重写了onCreate()onUpgrade()。所有写操作都封装在TransactionDao接口中,并由SQLiteTransactionDao实现。重点看insertBatch()方法——它用于初始化演示数据或导入 CSV:

public long insertBatch(List<Transaction> transactions) { SQLiteDatabase db = this.getWritableDatabase(); db.beginTransaction(); try { for (Transaction t : transactions) { ContentValues values = new ContentValues(); values.put("amount", t.getAmount()); values.put("date", t.getDate()); // 已格式化为字符串 values.put("category", t.getCategory()); values.put("note", t.getNote()); db.insert("expense", null, values); // 注意:此处仅处理 expense 表 } db.setTransactionSuccessful(); return transactions.size(); } finally { db.endTransaction(); } }
参数说明:
  • getWritableDatabase():确保获得可写数据库实例,若首次创建会触发onCreate()
  • beginTransaction()/endTransaction():显式事务边界,防止中途崩溃导致数据不一致
  • setTransactionSuccessful():必须调用,否则endTransaction()会回滚全部操作

注意:该方法目前只支持expense表,若需同时插入 income,应在 DAO 层扩展insertIncomeBatch()并在业务层统一管理事务。源码中未实现跨表事务,这是课程设计可拓展点之一。

2.3 UI 层关键组件:RecyclerView 多类型适配器与图表联动

主界面MainActivity使用BottomNavigationView切换三个 Tab:首页(统计概览)、记账页(收支录入)、备忘录。其中首页的统计卡片区域由RecyclerView实现,其AdapterStatisticsAdapter,支持两种 ViewHolder:

  • ChartViewHolder:加载MPAndroidChartPieChartBarChart
  • SummaryViewHolder:显示「本月结余」「总支出占比」等文字摘要

图表数据生成逻辑在ChartUtils.java中:

public static PieData generateExpensePieData(List<Expense> expenses) { List<PieEntry> entries = new ArrayList<>(); Map<Integer, Float> categorySum = new HashMap<>(); // key: category, value: sum for (Expense e : expenses) { int cat = e.getCategory(); float sum = categorySum.getOrDefault(cat, 0f) + (float) e.getAmount(); categorySum.put(cat, sum); } for (Map.Entry<Integer, Float> entry : categorySum.entrySet()) { String label = getCategoryName(entry.getKey()); // 调用工具方法转中文 entries.add(new PieEntry(entry.getValue(), label)); } PieDataSet dataSet = new PieDataSet(entries, "支出分类"); dataSet.setColors(ColorTemplate.MATERIAL_COLORS); return new PieData(dataSet); }
关键参数解释:
  • PieEntry(value, label):value 是数值,label 是显示文字,二者严格分离
  • ColorTemplate.MATERIAL_COLORS:使用 Material Design 预设色板,避免手写 RGB 值导致配色混乱
  • generateExpensePieData()返回PieData,直接传给PieChart.setData()即可刷新

提示:源码中BarChart显示的是「近7日每日支出趋势」,其 X 轴标签通过IndexAxisValueFormatter动态生成,而非静态数组。这保证了日期滚动时标签自动更新,是图表交互细节的加分项。

3. 编译运行与真机调试:Android Studio 环境配置与常见构建问题排查

拿到.rar解压后的工程目录,不能直接打开就编译成功。课程设计级项目往往忽略 Gradle 版本兼容性与 SDK 路径绑定,需手动校准。以下步骤基于 Android Studio Giraffe | 2022.3.1(当前主流稳定版)验证通过。

3.1 工程导入前的必要检查项

解压后进入根目录,确认存在以下文件结构:

/app/ /src/main/ /java/com/example/finance/ ← Java 源码入口 /res/ ← layout、drawable、values 等资源 AndroidManifest.xml /build.gradle ← Module 级构建脚本 /settings.gradle

若缺失gradle/wrapper/gradle-wrapper.properties,需手动创建,内容如下(匹配源码中build.gradle声明的 Gradle 版本):

distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists

提示:源码中build.gradlecompileSdk为 33,targetSdk为 33,因此必须安装 Android SDK Platform 33。在 Android Studio → SDK Manager → SDK Platforms 中勾选「Android 13.0 (Tiramisu)」并安装。

3.2 修改 build.gradle 以适配新版本 Android Studio

原始app/build.gradle中存在两处需调整:

(1)替换已废弃的插件写法
// ❌ 旧写法(Gradle < 7.0) apply plugin: 'com.android.application' // ✅ 新写法(Gradle ≥ 7.0) plugins { id 'com.android.application' }
(2)更新依赖库版本号

源码中implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'在新环境下可能因 JitPack 证书问题拉取失败。改为使用 MavenCentral 托管的稳定版:

// 替换原 MPAndroidChart 依赖 implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' // 改为 ↓ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' // 此行保留,但需在项目级 build.gradle 添加 jitpack 仓库

并在项目根目录build.gradle(或settings.gradle)中添加:

dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() maven { url 'https://jitpack.io' } // 必加!否则 MPAndroidChart 报错 } }

3.3 真机运行时的关键日志定位与修复

部署到真机后若白屏或闪退,按以下顺序查日志:

步骤 1:过滤Finance相关异常

在 Android Studio → Logcat 中设置过滤器:

package:com.example.finance

并选择Error级别。常见报错如下:

错误信息原因修复方式
android.database.sqlite.SQLiteException: no such table: expense数据库未创建成功检查FinanceDatabaseHelperonCreate()是否被调用,可在构造函数中加Log.d("DB", "Helper created")验证
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.github.mikephil.charting.charts.PieChart.setData(...)'PieChart 控件 ID 写错或未 findViewById检查activity_main.xmlPieChartandroid:id是否为@+id/pieChart,且 Java 中findViewById(R.id.pieChart)调用位置在setContentView()之后
Caused by: java.text.ParseException: Unparseable date: "2023-10-05"日期格式化器未指定 LocaleDateUtils.java中将SimpleDateFormat("yyyy-MM-dd")改为new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
步骤 2:验证数据库内容

使用adb shell进入设备数据库目录(需开启 USB 调试与 OEM Unlock):

adb shell run-as com.example.finance cd databases ls -l # 应看到 finance.db 文件 sqlite3 finance.db .tables # 查看表名,应输出 expense、income、memo select * from expense limit 3; # 查看前三条支出记录 .quit

注意:run-as命令仅对 debug 包生效。若提示Permission denied,说明 APK 是 release 签名,需改用adb backup导出再用 DB Browser for SQLite 查看。

4. 功能增强与实战迁移:如何将课程设计升级为可展示的简历项目

仅仅跑通源码只是起点。要让这个理财 App 在技术面试中脱颖而出,必须完成至少一项「可验证的增强」。以下是三个经过验证的进阶方向,每个都附带可立即执行的代码片段与效果说明。

4.1 增加「收支趋势对比图」:双 Y 轴 BarLineChart 实现

MPAndroidChart 支持在同一图表中叠加柱状图(支出)与折线图(收入),形成直观对比。修改StatisticsAdapter中的onBindViewHolder()

// 在生成图表数据后,构建 CombinedData CombinedData combinedData = new CombinedData(); BarData barData = new BarData(generateExpenseBarData(expenses)); // 近7日支出 barData.setDrawValues(false); // 隐藏柱子顶部数值,避免遮挡 LineData lineData = new LineData(generateIncomeLineData(incomes)); // 近7日收入 lineData.setDrawValues(false); combinedData.setData(barData); combinedData.setData(lineData); // 设置双 Y 轴 YAxis leftAxis = chart.getAxisLeft(); leftAxis.setAxisMinimum(0f); YAxis rightAxis = chart.getAxisRight(); rightAxis.setAxisMinimum(0f); chart.setData(combinedData); chart.invalidate(); // 刷新视图
效果验证:
  • X 轴显示「周一至周日」7 个日期标签
  • 左侧 Y 轴为支出金额(蓝色柱状图)
  • 右侧 Y 轴为收入金额(红色折线图)
  • 图表底部自动显示图例(Legend)

提示:generateIncomeLineData()需自行实现,逻辑与generateExpenseBarData()类似,但返回LineDataSet。此功能使统计页信息密度提升 200%,面试官一眼可见数据维度丰富性。

4.2 实现「备忘录关键词高亮」:SpannableStringBuilder 动态着色

源码中备忘录仅用TextView显示纯文本。增强后支持识别#紧急@张三¥500等模式并着色:

public static SpannableStringBuilder highlightKeywords(String text) { SpannableStringBuilder builder = new SpannableStringBuilder(text); // 匹配 #开头的标签,如 #医疗 #交通 Pattern tagPattern = Pattern.compile("#[\\u4e00-\\u9fa5a-zA-Z0-9_]+"); Matcher tagMatcher = tagPattern.matcher(text); while (tagMatcher.find()) { int start = tagMatcher.start(); int end = tagMatcher.end(); builder.setSpan(new ForegroundColorSpan(Color.parseColor("#FF6200EE")), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } // 匹配 ¥开头的金额,如 ¥129.5 Pattern moneyPattern = Pattern.compile("¥\\d+(\\.\\d{1,2})?"); Matcher moneyMatcher = moneyPattern.matcher(text); while (moneyMatcher.find()) { int start = moneyMatcher.start(); int end = moneyMatcher.end(); builder.setSpan(new ForegroundColorSpan(Color.parseColor("#FF00C853")), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } return builder; }

MemoDetailActivity中调用:

TextView memoContent = findViewById(R.id.memo_content); memoContent.setText(highlightKeywords(memo.getText()));
参数说明:
  • Spannable.SPAN_EXCLUSIVE_EXCLUSIVE:确保高亮范围不随文本增删而扩散
  • #FF6200EE是深紫色(Material Purple 700),#FF00C853是青绿色(Material Green A400)
  • 正则表达式\\u4e00-\\u9fa5匹配中文,避免英文标签误判

注意:此功能无需修改数据库结构,纯前端增强,5 分钟即可集成,但能显著体现对 Android 文本渲染机制的理解深度。

4.3 添加「数据导出为 CSV」功能:FileProvider 安全分享

课程设计常忽略数据主权。增加「导出本月收支为 CSV」按钮,使用FileProvider规避 Android 7.0+ 的file://限制:

步骤 1:在AndroidManifest.xml中声明 provider
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
步骤 2:创建res/xml/file_paths.xml
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="external_files/" path="."/> </paths>
步骤 3:编写导出逻辑(在MainActivity中)
private void exportToCsv() { File csvFile = new File(getExternalFilesDir(null), "finance_export_" + new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()) + ".csv"); try (FileWriter writer = new FileWriter(csvFile)) { writer.append("日期,类型,金额,分类,备注\n"); for (Expense e : expenses) { writer.append(String.format(Locale.getDefault(), "%s,支出,%.2f,%s,%s\n", e.getDate(), e.getAmount(), getCategoryName(e.getCategory()), e.getNote())); } for (Income i : incomes) { writer.append(String.format(Locale.getDefault(), "%s,收入,%.2f,%s,%s\n", i.getDate(), i.getAmount(), getCategoryName(i.getCategory()), i.getNote())); } // 通过 FileProvider 分享 Uri contentUri = FileProvider.getUriForFile( this, getPackageName() + ".fileprovider", csvFile ); Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/csv"); intent.putExtra(Intent.EXTRA_STREAM, contentUri); startActivity(Intent.createChooser(intent, "分享 CSV 文件")); } catch (IOException e) { Toast.makeText(this, "导出失败:" + e.getMessage(), Toast.LENGTH_SHORT).show(); } }
验证方式:
  • 点击导出按钮 → 选择微信/QQ → 发送成功后在 PC 端打开 CSV,确认字段对齐、中文不乱码
  • 查看Android/data/com.example.finance/files/目录下是否生成对应文件(需文件管理器开启显示隐藏目录)

提示:此功能直击企业级 App 的合规要求(用户数据可携带),且涉及FileProviderUri权限、Intent分享链路三个高频面试考点,是课程设计向工业级实践跃迁的关键锚点。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 4:44:47

VS Code搭建STM32嵌入式开发环境实战指南

1. 为什么STM32开发者正在集体“逃离”Keil&#xff0c;转向VS Code&#xff1f;我第一次在客户现场看到工程师用VS Code调试STM32F407时&#xff0c;他正把一个带FreeRTOS的电机控制项目从Keil uVision里“拖”出来——不是导出工程&#xff0c;而是手动复制源码、头文件、启动…

作者头像 李华
网站建设 2026/9/10 4:44:37

昇腾/GE异步操作符重载示例

Sample Usage Guide 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch、Tensor…

作者头像 李华
网站建设 2026/9/10 4:42:40

CamoFox-Browser:基于Firefox ESR的反爬伪装运行时方案

1. 项目概述&#xff1a;CamoFox-Browser不是浏览器&#xff0c;而是一套“隐身式”自动化控制方案你搜“camofox-browser”&#xff0c;页面上跳出来的全是Firefox、C、Playwright、Puppeteer这些词——但根本找不到一个叫“CamoFox Browser”的官方产品、GitHub仓库或下载链接…

作者头像 李华
网站建设 2026/9/10 4:39:59

AST驱动的规约协同开发:手机端指挥Kiro+Claude+Codex工作流

1. 项目概述&#xff1a;这不是一个“手机App”&#xff0c;而是一套可落地的规约协同工作流 你看到标题里写着“手机端掌控 Kiro”&#xff0c;第一反应可能是——又一个吹嘘移动端功能的营销话术&#xff1f;别急&#xff0c;我用三台不同型号的安卓手机&#xff08;Pixel 7、…

作者头像 李华
网站建设 2026/9/10 4:37:21

免费物联网云平台选型与组态实操:从OneNET到FUXA

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华