Files
2026-09-04 15:22:20 +08:00

55 lines
2.0 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:async';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:new_learn/core/storage/stores/answer_record_store.dart';
/// ============================================================
/// 【answerProvider】答题状态 —— Riverpod 内存主状态
///
/// 一、架构定位(对应方案分析结论):
/// 答案主状态必须住内存(每题作答高频读写、交卷即弃),
/// Isar 只是"备份恢复层":每次作答同步写一条 AnswerRecord,
/// 进程杀掉后下次进卷按 paperId 读回 restore() 续答。
///
/// 二、数据结构:`Map<questionId, String>`
/// key 用服务器题号(Question.questionId),不依赖本地自增 id,
/// 这样续答恢复时即使题目重新拉取也能对上。
///
/// 三、持久化为什么 fire-and-forget:
/// put 走 Isar 毫秒级完成,没必要阻塞 UI 作答回调;
/// web 端 store 是空实现(打印跳过),行为自动降级为纯内存。
/// ============================================================
/// Demo 试卷 id(真实项目由试卷对象传入,如 paper.paperId)
const int demoPaperId = 1001;
final answerProvider =
NotifierProvider<AnswerNotifier, Map<int, String>>(AnswerNotifier.new);
class AnswerNotifier extends Notifier<Map<int, String>> {
@override
Map<int, String> build() => {};
/// 【作答】更新内存 + 同步落盘(续答持久化)
void answer(int questionId, String value) {
state = {...state, questionId: value};
// fire-and-forget:写库毫秒级,不阻塞作答回调
unawaited(
AnswerRecordStore.instance.put(
paperId: demoPaperId,
questionId: questionId,
answer: value,
),
);
}
/// 【续答恢复】进卷时从 Isar 读回,整体注入(只恢复本卷存在的题)
void restore(Map<int, String> saved) {
if (saved.isEmpty) return;
state = {...state, ...saved};
}
/// 【交卷清理】清空内存状态(Isar 记录由页面调 deleteByPaper)
void clear() => state = {};
}