You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中重写Drift表==运算符遇异步解密问题求解决方案

解决Drift表类异步解密下的相等性判断问题

由于operator==是同步方法,无法直接在里面调用异步解密逻辑,这里提供几个可行的替代方案:

方案1:分离实体与解密后的业务模型

创建一个专门用于业务层的DecryptedUser类,将数据库实体Users的加密字段解密后存入该类,再在这个类中重写相等性判断逻辑。这种方式遵循单一职责原则,把数据库存储和业务逻辑解耦。

class DecryptedUser {
  final String id;
  final String? username;
  final String? password;

  DecryptedUser({required this.id, this.username, this.password});

  // 从Users实体异步生成解密后的模型
  static Future<DecryptedUser> fromUser(Users user) async {
    final decryptedUsername = await Users.decrypt(user.username);
    final decryptedPassword = await Users.decrypt(user.password);
    return DecryptedUser(
      id: user.id,
      username: decryptedUsername,
      password: decryptedPassword,
    );
  }

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is DecryptedUser &&
          runtimeType == other.runtimeType &&
          id == other.id &&
          username == other.username &&
          password == other.password;

  @override
  int get hashCode => id.hashCode ^ username.hashCode ^ password.hashCode;
}

使用时先将Users转换为DecryptedUser,之后就能用同步的==判断相等性。

方案2:缓存解密结果到实体类

在Users类中添加私有变量存储解密后的字段值,通过异步方法提前初始化缓存,之后在operator==中直接使用缓存值判断。

@DataClassName('User')
class Users extends Table {
  TextColumn get id => text().clientDefault(() => uuid.v4())();
  TextColumn get username => text().nullable()();
  TextColumn get password => text().nullable()();
    
  @override
  Set<Column> get primaryKey => {id};

  // 缓存解密后的字段值
  String? _decryptedUsername;
  String? _decryptedPassword;

  // 异步初始化解密缓存
  Future<void> decryptValues() async {
    _decryptedUsername = await decrypt(username);
    _decryptedPassword = await decrypt(password);
  }

  static Future<String?> decrypt(String? cipherText) async {
    if (cipherText == null) return null;

    final key = await getEncryptionKey();
    final decoded = base64.decode(cipherText);
    final iv = IV.fromLength(ivLength);
    final encrypter = Encrypter(AES(key));

    final encrypted = Encrypted(decoded.sublist(16));
    final decrypted = encrypter.decrypt(encrypted, iv: iv);
    return decrypted;
  }

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is Users &&
          runtimeType == other.runtimeType &&
          id == other.id &&
          _decryptedUsername == other._decryptedUsername &&
          _decryptedPassword == other._decryptedPassword;

  @override
  int get hashCode => id.hashCode ^ _decryptedUsername.hashCode ^ _decryptedPassword.hashCode;
}

注意:必须先调用decryptValues()初始化缓存,否则==判断会因缓存为空而失效;如果原加密字段被修改,需要手动清空缓存并重新调用解密方法。

方案3:使用异步方法替代同步operator==

直接在Users类中定义一个异步的相等判断方法,放弃重写operator==,业务代码中通过await调用该方法判断相等性。

@DataClassName('User')
class Users extends Table {
  // 原表定义不变...

  static Future<String?> decrypt(String? cipherText) async {
    // 原解密逻辑不变
  }

  // 异步判断两个Users实例是否相等
  Future<bool> isEqualTo(Users other) async {
    if (identical(this, other)) return true;
    if (id != other.id) return false;

    final myUsername = await decrypt(username);
    final otherUsername = await decrypt(other.username);
    final myPassword = await decrypt(password);
    final otherPassword = await decrypt(other.password);

    return myUsername == otherUsername && myPassword == otherPassword;
  }
}

这种方式无需改动原有实体结构,但业务代码需要适配异步调用逻辑。

内容的提问来源于stack exchange,提问作者Questions100

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 23:23:24