persistence.dart 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. import 'dart:async';
  2. import 'dart:convert'; // 导入 json 编码解码
  3. import 'dart:io';
  4. import 'package:image_puzzle/models/items.dart';
  5. import 'package:package_info_plus/package_info_plus.dart';
  6. import 'package:rate_my_app/rate_my_app.dart';
  7. import 'package:shared_preferences/shared_preferences.dart';
  8. import 'package:uuid/uuid.dart';
  9. ///持久化存储数据
  10. ///全局类
  11. class Persistence {
  12. late final SharedPreferences _prefs;
  13. Persistence._internal();
  14. static final Persistence _instance = Persistence._internal();
  15. factory Persistence() => _instance;
  16. int get projectId {
  17. if (Platform.isAndroid) {
  18. return 9;
  19. } else if (Platform.isIOS) {
  20. return 10;
  21. }
  22. return 0;
  23. }
  24. String get libraryName {
  25. if (Platform.isAndroid) {
  26. return "android";
  27. } else if (Platform.isIOS) {
  28. return "ios";
  29. }
  30. return "unkown";
  31. }
  32. late String packageVersion;
  33. ///初始化并给各参数分配默认值
  34. Future<void> initialize() async {
  35. PackageInfo packageInfo = await PackageInfo.fromPlatform();
  36. packageVersion = packageInfo.version;
  37. _prefs = await SharedPreferences.getInstance();
  38. //系统
  39. _uuid = PreferencesValue<String>('uuid', const Uuid().v4(), _prefs);
  40. _firstRunTime = PreferencesValue<DateTime>('first_run_time', DateTime.now(), _prefs, saveDefault: true);
  41. _lastRunTime = PreferencesValue<DateTime>('last_run_time', DateTime.now(), _prefs, saveDefault: true);
  42. _lastDailyRewardTime = PreferencesValue<DateTime>('last_daily_reward_time', DateTime.now().subtract(const Duration(days: 1)), _prefs);
  43. //评分
  44. _rating = PreferencesValue<double>('rating', 0, _prefs);
  45. _rateShowTimes = PreferencesValue<int>('rate_show_times', 0, _prefs);
  46. _rateLastShowTime = PreferencesValue<DateTime>('last_rate_show_time', DateTime.now().subtract(const Duration(days: 1)), _prefs);
  47. //settings
  48. _sound = PreferencesValue<bool>('sound', true, _prefs);
  49. _music = PreferencesValue<bool>('music', true, _prefs);
  50. _vibrate = PreferencesValue<bool>('vibrate', true, _prefs);
  51. _skin = PreferencesValue<int>('skin', 0, _prefs);
  52. //banner 广告收益
  53. _lastBannerPaidReportTimestamp = PreferencesValue<int>('last_banner_paid_report_timestamp', DateTime.now().millisecondsSinceEpoch, _prefs);
  54. _bannerPaidValueMicros = PreferencesValue<double>('banner_paid_value_micros', 0, _prefs);
  55. // !!! 改造点:完成作品集 - 存储 Work 对象列表
  56. _completedWorks = PreferencesValue<List<Work>>(
  57. 'completed_works',
  58. [],
  59. _prefs,
  60. encoder: (list) => list.map((w) => jsonEncode(w.toJson())).toList(), // 序列化
  61. decoder: (jsonList) => jsonList.map((jsonStr) => Work.fromJson(jsonDecode(jsonStr))).toList(), // 反序列化
  62. );
  63. // !!! 改造点:完成收藏图集 - 存储 Work 对象列表
  64. _completedCollections = PreferencesValue<List<Work>>(
  65. 'completed_collections',
  66. [],
  67. _prefs,
  68. encoder: (list) => list.map((c) => jsonEncode(c.toJson())).toList(), // 序列化
  69. decoder: (jsonList) => jsonList.map((jsonStr) => Work.fromJson(jsonDecode(jsonStr))).toList(), // 反序列化
  70. );
  71. }
  72. // uuid
  73. late PreferencesValue<String> _uuid;
  74. String get uuid => _uuid.value;
  75. set uuid(String value) => _uuid.value = value;
  76. // 程序第一次运行
  77. late PreferencesValue<DateTime> _firstRunTime;
  78. DateTime get firstRunTime => _firstRunTime.value;
  79. set firstRunTime(DateTime value) => _firstRunTime.value = value;
  80. //程序最后一次运行时间
  81. late PreferencesValue<DateTime> _lastRunTime;
  82. DateTime get lastRunTime => _lastRunTime.value;
  83. set lastRunTime(DateTime value) => _lastRunTime.value = value;
  84. //上一次 daily reward 时间
  85. late PreferencesValue<DateTime> _lastDailyRewardTime;
  86. DateTime get lastDailyRewardTime => _lastDailyRewardTime.value;
  87. set lastDailyRewardTime(DateTime value) => _lastDailyRewardTime.value = value;
  88. //评分
  89. late PreferencesValue<double> _rating;
  90. double get rating => _rating.value;
  91. set rating(double value) => _rating.value = value;
  92. //评分弹框次数
  93. late PreferencesValue<int> _rateShowTimes;
  94. int get rateShowTimes => _rateShowTimes.value;
  95. set rateShowTimes(int value) => _rateShowTimes.value = value;
  96. //评分上次弹框时间
  97. late PreferencesValue<DateTime> _rateLastShowTime;
  98. DateTime get rateLastShowTime => _rateLastShowTime.value;
  99. set rateLastShowTime(DateTime value) => _rateLastShowTime.value = value;
  100. // 各种按键声音效果
  101. late PreferencesValue<bool> _sound;
  102. bool get sound => _sound.value;
  103. set sound(bool value) => _sound.value = value;
  104. // 背景音乐
  105. late PreferencesValue<bool> _music;
  106. bool get music => _music.value;
  107. set music(bool value) => _music.value = value;
  108. // 振动
  109. late PreferencesValue<bool> _vibrate;
  110. bool get vibrate => _vibrate.value;
  111. set vibrate(bool value) => _vibrate.value = value;
  112. // 皮肤方案
  113. late PreferencesValue<int> _skin;
  114. int get skin => _skin.value;
  115. set skin(int value) => _skin.value = value;
  116. // banner 上一次广告收益上报时间
  117. late PreferencesValue<int> _lastBannerPaidReportTimestamp;
  118. int get lastBannerPaidReportTimestamp => _lastBannerPaidReportTimestamp.value;
  119. set lastBannerPaidReportTimestamp(int value) => _lastBannerPaidReportTimestamp.value = value;
  120. // banner 广告收益累积金额
  121. late PreferencesValue<double> _bannerPaidValueMicros;
  122. double get bannerPaidValueMicros => _bannerPaidValueMicros.value;
  123. set bannerPaidValueMicros(double value) => _bannerPaidValueMicros.value = value;
  124. // !!! 改造点:已完成作品集合
  125. late PreferencesValue<List<Work>> _completedWorks;
  126. List<Work> get completedWorks => _completedWorks.value;
  127. set completedWorks(List<Work> value) => _completedWorks.value = value;
  128. // !!! 改造点:已完成收藏集合
  129. late PreferencesValue<List<Work>> _completedCollections;
  130. List<Work> get completedCollections => _completedCollections.value;
  131. set completedCollections(List<Work> value) => _completedCollections.value = value;
  132. }
  133. ///----------------------------
  134. class PreferencesValue<T> {
  135. final String key;
  136. final T defaultValue;
  137. final SharedPreferences prefs;
  138. // 新增:用于自定义对象列表的编码和解码函数
  139. final List<String> Function(T value)? encoder;
  140. final T Function(List<String> jsonList)? decoder;
  141. late T _value;
  142. T get value => _value;
  143. set value(T v) {
  144. _value = v;
  145. if (_value is bool) {
  146. unawaited(prefs.setBool(key, _value as bool));
  147. } else if (_value is int) {
  148. unawaited(prefs.setInt(key, _value as int));
  149. } else if (_value is String) {
  150. unawaited(prefs.setString(key, _value as String));
  151. } else if (_value is double) {
  152. unawaited(prefs.setDouble(key, _value as double));
  153. } else if (_value is DateTime) {
  154. unawaited(prefs.setInt(key, (_value as DateTime).millisecondsSinceEpoch));
  155. } // !!! 改造点:处理 List<CompletedWork> 或 List<CompletedCollection>
  156. else if (_value is List<String> && encoder == null) {
  157. // 兼容旧的List<String>
  158. unawaited(prefs.setStringList(key, _value as List<String>));
  159. } else if (_value is List && encoder != null) {
  160. // 针对自定义对象列表
  161. unawaited(prefs.setStringList(key, encoder!(_value))); // 使用 encoder 编码
  162. }
  163. // 注意:这里没有对List<T> (非List<String>) 和非列表的自定义T进行处理,
  164. // 如果有其他非List<String>的自定义T需要持久化,需要在这里添加逻辑,
  165. // 例如通过 jsonEncode(value.toJson()) / T.fromJson(jsonDecode(string))
  166. }
  167. PreferencesValue(this.key, this.defaultValue, this.prefs, {bool saveDefault = false, this.encoder, this.decoder}) {
  168. _value = defaultValue;
  169. bool isExist = prefs.containsKey(key);
  170. if (_value is bool) {
  171. _value = (prefs.getBool(key) ?? defaultValue) as T;
  172. if (!isExist && saveDefault) unawaited(prefs.setBool(key, _value as bool));
  173. } else if (_value is int) {
  174. _value = (prefs.getInt(key) ?? defaultValue) as T;
  175. if (!isExist && saveDefault) unawaited(prefs.setInt(key, _value as int));
  176. } else if (_value is String) {
  177. _value = (prefs.getString(key) ?? defaultValue) as T;
  178. if (!isExist && saveDefault) unawaited(prefs.setString(key, _value as String));
  179. } else if (_value is double) {
  180. _value = (prefs.getDouble(key) ?? defaultValue) as T;
  181. if (!isExist && saveDefault) unawaited(prefs.setDouble(key, _value as double));
  182. } else if (_value is DateTime) {
  183. int? tmp = prefs.getInt(key);
  184. _value = (tmp == null ? defaultValue : DateTime.fromMillisecondsSinceEpoch(tmp)) as T;
  185. if (!isExist && saveDefault) unawaited(prefs.setInt(key, (_value as DateTime).millisecondsSinceEpoch));
  186. } // !!! 改造点:处理 List<CompletedWork> 或 List<CompletedCollection>
  187. else if (_value is List<String> && decoder == null) {
  188. // 兼容旧的List<String>
  189. _value = (prefs.getStringList(key) ?? defaultValue) as T;
  190. if (!isExist && saveDefault) unawaited(prefs.setStringList(key, _value as List<String>));
  191. } else if (_value is List && decoder != null) {
  192. // 针对自定义对象列表
  193. final List<String>? jsonList = prefs.getStringList(key);
  194. if (jsonList != null && jsonList.isNotEmpty) {
  195. _value = decoder!(jsonList); // 使用 decoder 反序列化
  196. } else {
  197. _value = defaultValue;
  198. }
  199. if (!isExist && saveDefault) unawaited(prefs.setStringList(key, encoder!(_value))); // 保存默认值
  200. }
  201. }
  202. }