Flutter记账应用中如何优化分类汇总模型以支持多维度筛选
改造CategorySummaryModel实现多维度收支汇总与实时更新
核心设计思路
- 用时间维度枚举统一管理日/月/年三种汇总维度
- 内部维护多维度汇总缓存,按「维度+时间键+分类ID+收支类型」分层存储数据
- 绑定TransactionModel的新增事件,触发汇总数据的实时同步
具体实现方案
1. 定义时间维度枚举
# 以Python为例,可根据技术栈调整 from enum import Enum class TimeDimension(Enum): DAY = "day" MONTH = "month" YEAR = "year"
2. 修改CategorySummaryModel结构
新增私有缓存属性,初始化时预加载全量交易的多维度汇总:
from collections import defaultdict class CategorySummaryModel: _summary_cache = { TimeDimension.DAY: defaultdict(lambda: {"income": 0.0, "expense": 0.0}), TimeDimension.MONTH: defaultdict(lambda: {"income": 0.0, "expense": 0.0}), TimeDimension.YEAR: defaultdict(lambda: {"income": 0.0, "expense": 0.0}) } def __init__(self, all_transactions): # 初始化时预计算各维度汇总 for dimension in TimeDimension: self._summary_cache[dimension] = self._calculate_summary(all_transactions, dimension) @staticmethod def _get_time_key(timestamp, dimension): # 生成标准时间键:日→YYYY-MM-DD,月→YYYY-MM,年→YYYY dt = timestamp.date() if dimension == TimeDimension.DAY: return dt.strftime("%Y-%m-%d") elif dimension == TimeDimension.MONTH: return dt.strftime("%Y-%m") elif dimension == TimeDimension.YEAR: return dt.strftime("%Y")
3. 实现多维度汇总计算逻辑
def _calculate_summary(self, transactions, dimension): summary = defaultdict(lambda: {"income": 0.0, "expense": 0.0}) for tx in transactions: time_key = self._get_time_key(tx.timestamp, dimension) # 用(时间键, 分类ID)作为缓存主键 cache_key = (time_key, tx.category_id) if tx.type == "income": summary[cache_key]["income"] += tx.amount else: summary[cache_key]["expense"] += tx.amount return summary
4. 对外暴露汇总查询接口
支持按维度、时间范围获取分类收支数据:
def get_category_summary(self, dimension, time_key=None): """ :param dimension: 时间维度(DAY/MONTH/YEAR) :param time_key: 可选,指定时间范围(如"2024-05"),不传则返回全量数据 """ if dimension not in self._summary_cache: return {} result = defaultdict(lambda: {"income": 0.0, "expense": 0.0}) for (tk, cat_id), data in self._summary_cache[dimension].items(): if not time_key or tk == time_key: result[cat_id]["income"] += data["income"] result[cat_id]["expense"] += data["expense"] # 关联分类名称(可选,需结合CategoryModel实现) for cat_id in result: result[cat_id]["category_name"] = CategoryModel.get_name_by_id(cat_id) return dict(result)
5. 实现新增交易的实时更新
在TransactionModel的新增方法中触发汇总更新:
# TransactionModel侧逻辑 class TransactionModel: @classmethod def add_transaction(cls, transaction): # 保存交易到持久化层 cls._save_transaction(transaction) # 触发汇总缓存更新 CategorySummaryModel.update_summary(transaction) # CategorySummaryModel侧更新逻辑 class CategorySummaryModel: @classmethod def update_summary(cls, transaction): for dimension in TimeDimension: time_key = cls._get_time_key(transaction.timestamp, dimension) cache_key = (time_key, transaction.category_id) if transaction.type == "income": cls._summary_cache[dimension][cache_key]["income"] += transaction.amount else: cls._summary_cache[dimension][cache_key]["expense"] += transaction.amount
额外优化点
- 若支持交易编辑/删除,复用上述
update_summary逻辑(先扣减旧数据,再加新数据) - 初始化时可异步加载全量汇总,避免阻塞应用启动
- 可定期与数据库全量数据校验缓存一致性,防止异常场景下的数据偏差
内容的提问来源于stack exchange,提问作者user22362195
相关产品推荐
相关产品推荐

