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
相关产品推荐
相关产品推荐

