Files
2026-09-15 15:44:13 +07:00

126 lines
3.9 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:convert';
import 'package:hgdj/hj_utils/text_util.dart';
import 'package:mmkv/mmkv.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../tools_base/debug_log.dart';
/// 轻量级别存储模型(kv键值对)内部包含文件和内存缓存
final lightKV = _LightModel();
class _LightModel {
MMKV? mmkv;
/// MMKV 不可用时的兜底:iOS release 包 FFI 符号被 stripMMKV 初始化抛 symbol not found
/// 会导致本地存储静默读写失败(如锁屏密码设置不上)。SharedPreferences 走 method channel
/// 不依赖 FFI,作为兜底保证纯本地功能可用。
SharedPreferences? _prefs;
bool get _useMmkv => mmkv != null;
Future config() async {
await init();
}
init() async {
if (mmkv != null || _prefs != null) return; // 已初始化(任一可用),避免重复
try {
final rootDir = await MMKV.initialize();
mmkv = MMKV.defaultMMKV(); // iOS release 若符号被 strip,这里会抛 symbol not found
debugLog('MMKV for flutter with rootDir = $rootDir');
} catch (e, s) {
// 兜底:MMKV 初始化失败不能把 main()/启动流程带崩,否则会卡在启动页
debugLog('MMKV init FAILED >>> $e\n$s');
}
// MMKV 起不来就启用 SharedPreferences 兜底
if (mmkv == null) {
try {
_prefs = await SharedPreferences.getInstance();
debugLog('MMKV unavailable, fallback to SharedPreferences');
} catch (e, s) {
debugLog('SharedPreferences init FAILED >>> $e\n$s');
}
}
}
void remove(String key) async {
await init();
if (_useMmkv) {
mmkv?.removeValue(key);
} else {
await _prefs?.remove(key);
}
}
Future<String?> getString(String key) async {
await init();
if (TextUtil.isEmpty(key)) return null;
if (_useMmkv) return mmkv?.decodeString(key);
return _prefs?.getString(key);
}
Future<bool?> setString(String key, String? value,
[bool genNewKey = true]) async {
await init();
if (TextUtil.isEmpty(key)) return false;
if (_useMmkv) return mmkv?.encodeString(key, value);
if (value == null) return await _prefs?.remove(key);
return await _prefs?.setString(key, value);
}
Future<int?> getInt(String? key) async {
await init();
if (TextUtil.isEmpty(key!)) return null;
if (_useMmkv) return mmkv?.decodeInt(key);
return _prefs?.getInt(key);
}
Future<bool?> setInt(String key, int value) async {
await init();
if (TextUtil.isEmpty(key)) return false;
if (_useMmkv) return mmkv?.encodeInt(key, value);
return await _prefs?.setInt(key, value);
}
Future<bool?> getBool(String? key, {bool defaultValue = false}) async {
await init();
if (TextUtil.isEmpty(key!)) return null;
if (_useMmkv) return mmkv?.decodeBool(key, defaultValue: defaultValue);
return _prefs?.getBool(key) ?? defaultValue;
}
Future<bool?> setBool(String key, bool value) async {
await init();
if (TextUtil.isEmpty(key)) return false;
if (_useMmkv) return mmkv?.encodeBool(key, value);
return await _prefs?.setBool(key, value);
}
Future<List<String>?> getStringList(String key,
[bool genNewKey = true]) async {
await init();
if (TextUtil.isEmpty(key)) return null;
if (_useMmkv) {
var jsonS = mmkv?.decodeString(key);
if (jsonS?.isNotEmpty == true) {
return parseStringList(json.decode(jsonS!));
}
return <String>[];
}
return _prefs?.getStringList(key) ?? <String>[];
}
///
Future<bool?> setStringList(String key, List<String> list,
[bool genNewKey = true]) async {
await init();
if (TextUtil.isEmpty(key)) return false;
if (_useMmkv) {
if (list.isEmpty) return mmkv?.encodeString(key, null);
return mmkv?.encodeString(key, json.encode(list));
}
return await _prefs?.setStringList(key, list);
}
}