Dart中多個系統(tǒng)封裝的多用戶單例管理實例

泛型單例管理器

import 'dart:convert';

import 'package:shared_preferences/shared_preferences.dart';

/// 泛型單例管理器
/// 用于管理不同類型用戶模型的本地存儲和更新
///
/// 使用示例:
/// ```dart
/// class UserModel {
///   final String id;
///   final String name;
///
///   UserModel({required this.id, required this.name});
///
///   factory UserModel.fromJson(Map<String, dynamic> json) {
///     return UserModel(
///       id: json['id'] as String,
///       name: json['name'] as String,
///     );
///   }
///
///   Map<String, dynamic> toJson() {
///     return {'id': id, 'name': name};
///   }
/// }
///
/// // 使用
/// final manager = SingleUserManager<UserModel>(
///   storageKey: 'user_manager',
///   fromJson: (json) => UserModel.fromJson(json),
/// );
///
/// // 初始化
/// await manager.initFromLocal();
///
/// // 更新
/// await manager.update(UserModel(id: '1', name: 'New Name'));
///
/// // 保存
/// await manager.save();
///
/// // 獲取當(dāng)前數(shù)據(jù)
/// final user = manager.current;
/// ```
class SingleUserManager<T> {
  /// 單例實例映射,使用類型字符串作為 key
  static final Map<String, SingleUserManager> _instances = {};

  /// 存儲鍵名
  final String storageKey;

  /// 從 JSON 創(chuàng)建實例的函數(shù)
  final T Function(Map<String, dynamic>) fromJson;

  /// SharedPreferences 實例
  SharedPreferences? _prefs;

  /// 當(dāng)前存儲的數(shù)據(jù)
  T? _currentData;

  /// 是否已初始化
  bool _isInitialized = false;

  /// 私有構(gòu)造函數(shù)
  SingleUserManager._internal({
    required this.storageKey,
    required this.fromJson,
  });

  /// 獲取單例實例
  /// [storageKey] 存儲鍵名,用于區(qū)分不同的管理器實例
  /// [fromJson] 從 JSON 創(chuàng)建實例的函數(shù)
  factory SingleUserManager({
    required String storageKey,
    required T Function(Map<String, dynamic>) fromJson,
  }) {
    final key = '$T$storageKey';
    return _instances.putIfAbsent(
          key,
          () => SingleUserManager._internal(
            storageKey: storageKey,
            fromJson: fromJson,
          ),
        )
        as SingleUserManager<T>;
  }

  /// 獲取當(dāng)前存儲的數(shù)據(jù)
  T? get current => _currentData;

  /// 檢查是否已初始化
  bool get isInitialized => _isInitialized;

  /// 檢查是否有數(shù)據(jù)
  bool get hasData => _currentData != null;

  /// 從本地存儲初始化數(shù)據(jù)
  /// 返回 true 表示成功加載數(shù)據(jù),false 表示沒有本地數(shù)據(jù)
  Future<bool> initFromLocal() async {
    try {
      _prefs ??= await SharedPreferences.getInstance();
      final jsonString = _prefs?.getString(storageKey);
      if (jsonString != null && jsonString.isNotEmpty) {
        final json = jsonDecode(jsonString) as Map<String, dynamic>;
        _currentData = fromJson(json);
        _isInitialized = true;
        return true;
      }
      _isInitialized = true;
      return false;
    } catch (e) {
      print('從本地初始化失敗 ($storageKey): $e');
      _isInitialized = true;
      _currentData = null;
      return false;
    }
  }

  /// 更新當(dāng)前數(shù)據(jù)
  /// [data] 新的數(shù)據(jù)對象
  Future<void> update(T data) async {
    _currentData = data;
  }

  /// 保存當(dāng)前數(shù)據(jù)到本地存儲
  /// 如果當(dāng)前沒有數(shù)據(jù),則不會執(zhí)行保存操作
  Future<void> save() async {
    if (_currentData == null) {
      print('沒有數(shù)據(jù)可保存 ($storageKey)');
      return;
    }
    try {
      _prefs ??= await SharedPreferences.getInstance();
      final json = _toJson(_currentData as T);
      final jsonString = jsonEncode(json);
      await _prefs!.setString(storageKey, jsonString);
    } catch (e) {
      print('保存數(shù)據(jù)失敗 ($storageKey): $e');
      rethrow;
    }
  }

  /// 更新并保存數(shù)據(jù)(便捷方法)
  /// [data] 新的數(shù)據(jù)對象
  Future<void> updateAndSave(T data) async {
    await update(data);
    await save();
  }

  /// 清除本地存儲的數(shù)據(jù)
  /// [clearCurrent] 是否同時清除當(dāng)前內(nèi)存中的數(shù)據(jù),默認為 true
  Future<void> clear({bool clearCurrent = true}) async {
    try {
      _prefs ??= await SharedPreferences.getInstance();
      await _prefs!.remove(storageKey);
      if (clearCurrent) {
        _currentData = null;
      }
    } catch (e) {
      print('清除數(shù)據(jù)失敗 ($storageKey): $e');
      rethrow;
    }
  }

  /// 將數(shù)據(jù)轉(zhuǎn)換為 JSON
  /// 嘗試動態(tài)調(diào)用 toJson 方法
  Map<String, dynamic> _toJson(T data) {
    try {
      final result = (data as dynamic).toJson();
      if (result is Map<String, dynamic>) {
        return result;
      }
      throw StateError('類型 $T 的 toJson() 方法必須返回 Map<String, dynamic>');
    } catch (e) {
      if (e is StateError) {
        rethrow;
      }
      throw StateError('類型 $T 必須實現(xiàn) toJson() 方法以支持序列化: $e');
    }
  }
}

/// 擴展方法:為實現(xiàn)了 toJson 的類型提供便捷的序列化支持
extension JsonSerializableExtension on Object {
  /// 嘗試將對象轉(zhuǎn)換為 JSON Map
  Map<String, dynamic>? tryToJson() {
    try {
      final result = (this as dynamic).toJson();
      if (result is Map<String, dynamic>) {
        return result;
      }
      return null;
    } catch (e) {
      return null;
    }
  }
}

// ==================== 使用示例 ====================

/// 示例 1: 普通用戶模型
class ExampleUser {
  final String id;
  final String name;
  final String? email;

  ExampleUser({required this.id, required this.name, this.email});

  factory ExampleUser.fromJson(Map<String, dynamic> json) {
    return ExampleUser(
      id: json['id'] as String,
      name: json['name'] as String,
      email: json['email'] as String?,
    );
  }

  Map<String, dynamic> toJson() {
    return {'id': id, 'name': name, if (email != null) 'email': email};
  }

  /// 獲取用戶管理器單例
  static SingleUserManager<ExampleUser> get manager =>
      SingleUserManager<ExampleUser>(
        storageKey: 'example_user',
        fromJson: (json) => ExampleUser.fromJson(json),
      );
}

/// 示例 2: 商戶用戶模型
class ExampleMerchant {
  final String merchantId;
  final String merchantName;
  final List<String> permissions;
  final DateTime? lastLoginTime;

  ExampleMerchant({
    required this.merchantId,
    required this.merchantName,
    required this.permissions,
    this.lastLoginTime,
  });

  factory ExampleMerchant.fromJson(Map<String, dynamic> json) {
    return ExampleMerchant(
      merchantId: json['merchantId'] as String,
      merchantName: json['merchantName'] as String,
      permissions: List<String>.from(json['permissions'] as List),
      lastLoginTime: json['lastLoginTime'] != null
          ? DateTime.parse(json['lastLoginTime'] as String)
          : null,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'merchantId': merchantId,
      'merchantName': merchantName,
      'permissions': permissions,
      if (lastLoginTime != null)
        'lastLoginTime': lastLoginTime!.toIso8601String(),
    };
  }

  /// 獲取商戶管理器單例
  static SingleUserManager<ExampleMerchant> get manager =>
      SingleUserManager<ExampleMerchant>(
        storageKey: 'example_merchant',
        fromJson: (json) => ExampleMerchant.fromJson(json),
      );
}

/// 使用示例代碼(在實際項目中可以這樣使用):
/// 
/// ```dart
/// // 1. 初始化并加載本地數(shù)據(jù)
/// final userManager = ExampleUser.manager;
/// final hasLocalData = await userManager.initFromLocal();
/// if (hasLocalData) {
///   final user = userManager.current;
///   print('加載用戶: ${user?.name}');
/// }
/// 
/// // 2. 更新用戶信息
/// final newUser = ExampleUser(
///   id: '123',
///   name: '張三',
///   email: 'zhangsan@example.com',
/// );
/// await userManager.update(newUser);
/// 
/// // 3. 保存到本地
/// await userManager.save();
/// 
/// // 或者直接更新并保存
/// await userManager.updateAndSave(newUser);
/// 
/// // 4. 獲取當(dāng)前用戶
/// final currentUser = userManager.current;
/// if (currentUser != null) {
///   print('當(dāng)前用戶: ${currentUser.name}');
/// }
/// 
/// // 5. 清除數(shù)據(jù)
/// await userManager.clear();
/// 
/// // 6. 管理多個不同的用戶類型
/// final merchantManager = ExampleMerchant.manager;
/// await merchantManager.initFromLocal();
/// 
/// final merchant = ExampleMerchant(
///   merchantId: 'm001',
///   merchantName: '測試商戶',
///   permissions: ['read', 'write'],
///   lastLoginTime: DateTime.now(),
/// );
/// await merchantManager.updateAndSave(merchant);
/// ```

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容