import 'dart:async'; import 'dart:convert'; // 导入 json 编码解码 import 'dart:io'; import 'package:image_puzzle/models/items.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:rate_my_app/rate_my_app.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:uuid/uuid.dart'; ///持久化存储数据 ///全局类 class Persistence { late final SharedPreferences _prefs; Persistence._internal(); static final Persistence _instance = Persistence._internal(); factory Persistence() => _instance; int get projectId { if (Platform.isAndroid) { return 9; } else if (Platform.isIOS) { return 10; } return 0; } String get libraryName { if (Platform.isAndroid) { return "android"; } else if (Platform.isIOS) { return "ios"; } return "unkown"; } late String packageVersion; ///初始化并给各参数分配默认值 Future initialize() async { PackageInfo packageInfo = await PackageInfo.fromPlatform(); packageVersion = packageInfo.version; _prefs = await SharedPreferences.getInstance(); //系统 _uuid = PreferencesValue('uuid', const Uuid().v4(), _prefs); _firstRunTime = PreferencesValue('first_run_time', DateTime.now(), _prefs, saveDefault: true); _lastRunTime = PreferencesValue('last_run_time', DateTime.now(), _prefs, saveDefault: true); _lastDailyRewardTime = PreferencesValue('last_daily_reward_time', DateTime.now().subtract(const Duration(days: 1)), _prefs); //评分 _rating = PreferencesValue('rating', 0, _prefs); _rateShowTimes = PreferencesValue('rate_show_times', 0, _prefs); _rateLastShowTime = PreferencesValue('last_rate_show_time', DateTime.now().subtract(const Duration(days: 1)), _prefs); //settings _sound = PreferencesValue('sound', true, _prefs); _music = PreferencesValue('music', true, _prefs); _vibrate = PreferencesValue('vibrate', true, _prefs); _skin = PreferencesValue('skin', 0, _prefs); //banner 广告收益 _lastBannerPaidReportTimestamp = PreferencesValue('last_banner_paid_report_timestamp', DateTime.now().millisecondsSinceEpoch, _prefs); _bannerPaidValueMicros = PreferencesValue('banner_paid_value_micros', 0, _prefs); // !!! 改造点:完成作品集 - 存储 Work 对象列表 _completedWorks = PreferencesValue>( 'completed_works', [], _prefs, encoder: (list) => list.map((w) => jsonEncode(w.toJson())).toList(), // 序列化 decoder: (jsonList) => jsonList.map((jsonStr) => Work.fromJson(jsonDecode(jsonStr))).toList(), // 反序列化 ); // !!! 改造点:完成收藏图集 - 存储 Work 对象列表 _completedCollections = PreferencesValue>( 'completed_collections', [], _prefs, encoder: (list) => list.map((c) => jsonEncode(c.toJson())).toList(), // 序列化 decoder: (jsonList) => jsonList.map((jsonStr) => Work.fromJson(jsonDecode(jsonStr))).toList(), // 反序列化 ); } // uuid late PreferencesValue _uuid; String get uuid => _uuid.value; set uuid(String value) => _uuid.value = value; // 程序第一次运行 late PreferencesValue _firstRunTime; DateTime get firstRunTime => _firstRunTime.value; set firstRunTime(DateTime value) => _firstRunTime.value = value; //程序最后一次运行时间 late PreferencesValue _lastRunTime; DateTime get lastRunTime => _lastRunTime.value; set lastRunTime(DateTime value) => _lastRunTime.value = value; //上一次 daily reward 时间 late PreferencesValue _lastDailyRewardTime; DateTime get lastDailyRewardTime => _lastDailyRewardTime.value; set lastDailyRewardTime(DateTime value) => _lastDailyRewardTime.value = value; //评分 late PreferencesValue _rating; double get rating => _rating.value; set rating(double value) => _rating.value = value; //评分弹框次数 late PreferencesValue _rateShowTimes; int get rateShowTimes => _rateShowTimes.value; set rateShowTimes(int value) => _rateShowTimes.value = value; //评分上次弹框时间 late PreferencesValue _rateLastShowTime; DateTime get rateLastShowTime => _rateLastShowTime.value; set rateLastShowTime(DateTime value) => _rateLastShowTime.value = value; // 各种按键声音效果 late PreferencesValue _sound; bool get sound => _sound.value; set sound(bool value) => _sound.value = value; // 背景音乐 late PreferencesValue _music; bool get music => _music.value; set music(bool value) => _music.value = value; // 振动 late PreferencesValue _vibrate; bool get vibrate => _vibrate.value; set vibrate(bool value) => _vibrate.value = value; // 皮肤方案 late PreferencesValue _skin; int get skin => _skin.value; set skin(int value) => _skin.value = value; // banner 上一次广告收益上报时间 late PreferencesValue _lastBannerPaidReportTimestamp; int get lastBannerPaidReportTimestamp => _lastBannerPaidReportTimestamp.value; set lastBannerPaidReportTimestamp(int value) => _lastBannerPaidReportTimestamp.value = value; // banner 广告收益累积金额 late PreferencesValue _bannerPaidValueMicros; double get bannerPaidValueMicros => _bannerPaidValueMicros.value; set bannerPaidValueMicros(double value) => _bannerPaidValueMicros.value = value; // !!! 改造点:已完成作品集合 late PreferencesValue> _completedWorks; List get completedWorks => _completedWorks.value; set completedWorks(List value) => _completedWorks.value = value; // !!! 改造点:已完成收藏集合 late PreferencesValue> _completedCollections; List get completedCollections => _completedCollections.value; set completedCollections(List value) => _completedCollections.value = value; } ///---------------------------- class PreferencesValue { final String key; final T defaultValue; final SharedPreferences prefs; // 新增:用于自定义对象列表的编码和解码函数 final List Function(T value)? encoder; final T Function(List jsonList)? decoder; late T _value; T get value => _value; set value(T v) { _value = v; if (_value is bool) { unawaited(prefs.setBool(key, _value as bool)); } else if (_value is int) { unawaited(prefs.setInt(key, _value as int)); } else if (_value is String) { unawaited(prefs.setString(key, _value as String)); } else if (_value is double) { unawaited(prefs.setDouble(key, _value as double)); } else if (_value is DateTime) { unawaited(prefs.setInt(key, (_value as DateTime).millisecondsSinceEpoch)); } // !!! 改造点:处理 List 或 List else if (_value is List && encoder == null) { // 兼容旧的List unawaited(prefs.setStringList(key, _value as List)); } else if (_value is List && encoder != null) { // 针对自定义对象列表 unawaited(prefs.setStringList(key, encoder!(_value))); // 使用 encoder 编码 } // 注意:这里没有对List (非List) 和非列表的自定义T进行处理, // 如果有其他非List的自定义T需要持久化,需要在这里添加逻辑, // 例如通过 jsonEncode(value.toJson()) / T.fromJson(jsonDecode(string)) } PreferencesValue(this.key, this.defaultValue, this.prefs, {bool saveDefault = false, this.encoder, this.decoder}) { _value = defaultValue; bool isExist = prefs.containsKey(key); if (_value is bool) { _value = (prefs.getBool(key) ?? defaultValue) as T; if (!isExist && saveDefault) unawaited(prefs.setBool(key, _value as bool)); } else if (_value is int) { _value = (prefs.getInt(key) ?? defaultValue) as T; if (!isExist && saveDefault) unawaited(prefs.setInt(key, _value as int)); } else if (_value is String) { _value = (prefs.getString(key) ?? defaultValue) as T; if (!isExist && saveDefault) unawaited(prefs.setString(key, _value as String)); } else if (_value is double) { _value = (prefs.getDouble(key) ?? defaultValue) as T; if (!isExist && saveDefault) unawaited(prefs.setDouble(key, _value as double)); } else if (_value is DateTime) { int? tmp = prefs.getInt(key); _value = (tmp == null ? defaultValue : DateTime.fromMillisecondsSinceEpoch(tmp)) as T; if (!isExist && saveDefault) unawaited(prefs.setInt(key, (_value as DateTime).millisecondsSinceEpoch)); } // !!! 改造点:处理 List 或 List else if (_value is List && decoder == null) { // 兼容旧的List _value = (prefs.getStringList(key) ?? defaultValue) as T; if (!isExist && saveDefault) unawaited(prefs.setStringList(key, _value as List)); } else if (_value is List && decoder != null) { // 针对自定义对象列表 final List? jsonList = prefs.getStringList(key); if (jsonList != null && jsonList.isNotEmpty) { _value = decoder!(jsonList); // 使用 decoder 反序列化 } else { _value = defaultValue; } if (!isExist && saveDefault) unawaited(prefs.setStringList(key, encoder!(_value))); // 保存默认值 } } }