Flutter Hive:自定义辅助函数中的类型抽象问题

问题描述 投票:0回答:1

我正在尝试使用自定义辅助函数和抽象类在 Flutter 应用程序中抽象我的 Hive 框打开逻辑,但在传递类型时遇到问题。非抽象的、冗长的代码可以工作,但我的抽象方法失败了。如何正确地将类型传递给我的抽象辅助函数?

在所有其他地方,我一直用它们的类型显式调用 Hive 框,例如 Hive.openBox(),这工作得很好。但是,我正在尝试重构我的代码以使其更加动态并避免重复。

为什么我会遇到这个问题?我尝试了多种类型检查和不同的方法,但似乎没有任何效果。任何有关如何正确实现这种抽象的指导将不胜感激。

我创建了一个最小的可重现示例,其中包含两个简单的自定义类来提供配置单元,它导致与我的大型项目完全相同的问题:

失败示例:

abstract class HiveDB {
  static Future<Box<dynamic>> secureEncryptedBox(
    dynamic object, {
    required String boxName,
  }) async {
    const secureStorage = FlutterSecureStorage();
    // if key not exists return null
    final encryptionKeyString = await secureStorage.read(key: 'key');
    if (encryptionKeyString == null) {
      final key = Hive.generateSecureKey();
      await secureStorage.write(
        key: 'key',
        value: base64UrlEncode(key),
      );
    }
    final key = await secureStorage.read(key: 'key');
    final encryptionKeyUint8List = base64Url.decode(key!);
    // Check if the box is already open, and open it with the correct type
    if (Hive.isBoxOpen(boxName)) {
      return TypeFilter.openHiveBoxExplicitly(object, boxName, encryptionKeyUint8List);
    }
    return TypeFilter.openHiveBoxExplicitlyAlternate(object, boxName, encryptionKeyUint8List);
  }
}

void main() async {
  await Hive.initFlutter();
  Hive.registerAdapter(UserAdapter());
  Hive.registerAdapter(ItemAdapter());
  await Hive.openBox('secureStorage'); // This box is used for secure keys
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Future<void> _saveData() async {
    final user = User(name: 'John Doe', age: 30);
    final item = Item(description: 'Sample Item', price: 19.99);

    Box<dynamic> userBox = await HiveDB.secureEncryptedBox(user, boxName: 'user_box');
    Box<dynamic> itemBox = await HiveDB.secureEncryptedBox(item, boxName: 'item_box');

    userBox.add(user);
    itemBox.add(item);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Hive Example'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: _saveData,
          child: Text('Save Data'),
        ),
      ),
    );
  }
}

// Abstract class TypeFilter
abstract class TypeFilter {
  static Future<Box<dynamic>> openHiveBoxExplicitly<T>(
    Type object,
    String boxName,
    List<int> encryptionKey,
  ) async {
    Box<dynamic> encryptedBox;
    if (object == User) {
      encryptedBox = await Hive.openBox<User>(
        boxName,
        encryptionCipher: HiveAesCipher(encryptionKey),
      );
    } else if (object == Item) {
      encryptedBox = await Hive.openBox<Item>(
        boxName,
        encryptionCipher: HiveAesCipher(encryptionKey),
      );
    } else {
      throw Exception("Unknown object type");
    }
    return encryptedBox;
  }

  static Future<Box<dynamic>> openHiveBoxExplicitlyAlternate(
    Type object,
    String boxName,
    List<int> encryptionKey,
  ) async {
    late Box<dynamic> encryptedBox;
    switch (object) {
      case User:
        encryptedBox = await Hive.openBox<User>(
          boxName,
          encryptionCipher: HiveAesCipher(encryptionKey),
        );
        break;
      case Item:
        encryptedBox = await Hive.openBox<Item>(
          boxName,
          encryptionCipher: HiveAesCipher(encryptionKey),
        );
        break;
      default:
        throw Exception("Unknown object type");
    }
    return encryptedBox;
  }
}

错误:

[VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: type 'User' is not a subtype of type 'Type'
#0      HiveDB.secureEncryptedBox
main.dart:30
<asynchronous suspension>
#1      _MyHomePageState._saveData
main.dart:61
<asynchronous suspension>

工作非抽象 HIVE 数据库代码:

note - 在我的实际项目中,我有一个巨大的 if 和 switch ,因为我有超过 15 个类,我试图抽象成这个方法。另外,作为信息,在我的主项目中,我需要带有“is”运算符的 if 语句以及带有对象切换的开关。为什么我不知道,这就是结果。我尝试使用 Reflectable 但没有运气,认为这可以解决这个问题。在我的主项目中,对象开关似乎在初始化应用程序时起作用,并且在保存在不同的配置中时,“is”运算符起作用,因为只有在保存或执行实际操作时我才传递实际对象。尽管如此,这里也有同样的问题,所以我做错了什么或者某个地方有问题......

abstract class HiveDB {
  static Future<Box<dynamic>> secureEncryptedBox(
    dynamic object, {
    required String boxName,
  }) async {
    const secureStorage = FlutterSecureStorage();
    // if key not exists return null
    final encryptionKeyString = await secureStorage.read(key: 'key');
    if (encryptionKeyString == null) {
      final key = Hive.generateSecureKey();
      await secureStorage.write(
        key: 'key',
        value: base64UrlEncode(key),
      );
    }
    final key = await secureStorage.read(key: 'key');
    final encryptionKeyUint8List = base64Url.decode(key!);
    late Box<dynamic> encryptedBox;
    // Check if the box is already open, and open it with the correct type
    if (Hive.isBoxOpen(boxName)) {
      if (object is User) {
        encryptedBox = await Hive.openBox<User>(
          boxName,
          encryptionCipher: HiveAesCipher(encryptionKeyUint8List),
        );
      } else if (object is Item) {
        encryptedBox = await Hive.openBox<Item>(
          boxName,
          encryptionCipher: HiveAesCipher(encryptionKeyUint8List),
        );
      }
    } else {
      // Open the box with the correct type if not already open
      switch (object.runtimeType) {
        case User:
          encryptedBox = await Hive.openBox<User>(
            boxName,
            encryptionCipher: HiveAesCipher(encryptionKeyUint8List),
          );
          break;
        case Item:
          encryptedBox = await Hive.openBox<Item>(
            boxName,
            encryptionCipher: HiveAesCipher(encryptionKeyUint8List),
          );
          break;
        default:
          throw Exception("Unknown object type");
      }
    }
    log(encryptedBox.runtimeType.toString());
    return encryptedBox;
  }
}

项目:


import 'package:hive/hive.dart';

import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';

part 'item.g.dart';

@HiveType(typeId: 1)
class Item {
  @HiveField(0)
  final String description;

  @HiveField(1)
  final double price;

  Item({required this.description, required this.price});
}

用户:

// user.dart

import 'package:hive/hive.dart';

import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';


part 'user.g.dart';

@HiveType(typeId: 0)
class User {
  @HiveField(0)
  final String name;

  @HiveField(1)
  final int age;

  User({required this.name, required this.age});
}
flutter types hive abstraction
1个回答
0
投票

TypeFilter.openHiveBox明确第一个参数需要Type。但在 HiveDB.secureEncryptedBox 中, 使用 TypeFilter.openHiveBoxExplicitly(object, boxName, cryptoKeyUint8List) 调用;当 HiveDB.secureEncryptedBox(user, boxName: 'user_box') 时,对象类型为 User; 用户不是类型的子类型;

因此您可以显式声明 TypeFilter.openHiveBox

static Future<Box<dynamic>> openHiveBoxExplicitly<T>(
    T object,
    String boxName,
    List<int> encryptionKey,
  ) async {
    if (object is User) {
      encryptedBox = await Hive.openBox<User>(
        boxName,
        encryptionCipher: HiveAesCipher(encryptionKey),
      );
    } else if (object is Item) {
      encryptedBox = await Hive.openBox<Item>(
        boxName,
        encryptionCipher: HiveAesCipher(encryptionKey),
      );
    } else {
      throw Exception("Unknown object type");
    }
    return encryptedBox;
  }
© www.soinside.com 2019 - 2024. All rights reserved.