上个月我给自己定了个挑战:两周内做出一款真正能跑通的记账类App MVP,用来验证"极简记账+月度复盘"这个需求到底有没有人买账。当时的硬性约束有三条:不搭服务器、不配数据库、不搞账号体系,所有数据全部落在本地文件里。最终项目第12天交付内测版,存储层全程用的是File-Based方案,一行数据库代码都没写。这篇文章把整个项目的构思、选型、实现步骤和踩坑记录完整复盘一遍,写给正在做MVP验证、或者对轻量级本地存储方案感兴趣的朋友。
先说结论:File-Based存储做MVP,核心价值不是"简单",而是"把验证成本压到最低"。数据量在几千条以内时,文件读写的性能完全够用,调试时直接打开文件就能看到数据长什么样,比查数据库爽太多。
1. 项目构思与方案定位
1.1 为什么选File-Based存储,而不是直接上数据库
很多人一听说要做App,第一反应就是"上SQLite"或者"接个云端数据库"。但在MVP阶段,这个选择往往是被惯性带着走的,而不是被需求推着走的。我这次特意压住这个冲动,用文件存储,背后有三个原因。
第一,MVP的核心目标是验证需求,不是验证架构。记账App的核心操作是"记一笔"和"看汇总",数据模型极其简单,就是一张流水表加一张分类表。这种量级下的增删改查,JSON文件完全扛得住。等到真的需要复杂查询、多端同步、万人并发的时候再换数据库,那时候需求已经被验证过了,换架构的成本是值得的。
第二,调试效率高得离谱。用数据库时,你要么连Android Studio的Database Inspector,要么装第三方工具,要么写SQL去查。用文件方案呢?直接把应用私有目录下的JSON文件拖出来,找个编辑器打开就能看。出问题了,人肉读文件比查日志都快。
第三,部署和分发成本为零。不需要在用户设备上初始化数据库、不需要处理版本迁移、不需要考虑服务器端存储。对MVP来说,这些省下来的时间全部可以投入到核心功能上。
1.2 MVP的边界到底怎么划
做MVP最常见的问题就是边界失控,功能越加越多,最后两周变成两个月。这次我给自己划了几条硬边界,现在看非常有效。
功能边界上,只做四件事:添加一笔账目、展示账目列表、按分类筛选、查看当月总支出。其余什么图表分析、预算管理、多账户、照片凭证、语音记账,全部砍掉。有些功能不是不好,而是第一版不该做。
用户边界上,不登录、不注册、不同步,默认单机单用户。好友分享、账单同步这些听起来很酷,但会让存储层复杂度直接翻几倍。File-Based方案最怕的就是多端并发写同一个文件,MVP阶段完全没必要给自己挖这个坑。
数据边界上,只保留最核心的字段:金额、分类、备注、时间。不做收支类型的双轨制,用正负数表示收入支出。这个决定让整个数据模型减少了一半的字段,文件读写和界面渲染都简单了很多。
1.3 技术栈选型思路
存储方案定了File-Based之后,上面的技术框架我选的是Flutter 3.x。理由很简单:我自己熟悉,而且Dart语言的dart:io结合path_provider插件,操作本地文件的API很直接,不需要额外引入重量级依赖。
如果你做的是原生Android项目,直接用java.io.File或者Kotlin的kotlin.io也能达到同样的效果;做iOS原生就用FileManager。关键是原理相通,都是把数据序列化成字符串,写到应用沙盒的私有目录里。我这里以Flutter为例展开,因为它的跨平台特性可以让这套存储层代码同时跑在Android和iOS上,正好符合MVP"快速验证"的定位。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 文件存储方案设计要点
2.1 数据模型与文件格式的选择
File-Based方案里,最核心的决定就是"用什么格式落盘"。我对比过三种主流格式,最终选了JSON。
CSV的好处是体积最小、可以用Excel直接打开编辑,但缺点是嵌套结构表达起来非常痛苦,比如一条账目如果对应多个标签,CSV处理起来就是灾难。Markdown/纯文本适合给人阅读的场景,但程序解析和写入的容错性差,一个格式错了整行数据就读不出来。JSON是JavaScrip
