Flutter 和 Hive 的奇怪问题

Posted

技术标签:

【中文标题】Flutter 和 Hive 的奇怪问题【英文标题】:Strange problems with Flutter and Hive 【发布时间】:2021-12-08 23:16:23 【问题描述】:

我在 Flutter 应用中遇到 Hive 数据库的几个问题:

    Hive.initFlutter() 不工作。我收到以下错误:
[VERBOSE-2:ui_dart_state.cc(209)] Unhandled Exception: HiveError: You need to initialize Hive or provide a path to store the box.

我尝试使用 appPath 调用该方法,而没有,它没有任何区别!如果我使用Hive.init(appPath) 而不是Hive.initFlutter() 我确实不会得到上述异常!这里是颤振应用程序中的代码: (Init 是一个有很多静态方法来初始化应用程序的类。它在闪屏小部件的FutureBuilder 中调用。首先调用setupLocalHiveDatabase() 方法来初始化 Hive 并打开所有框。)

void main() async 
  WidgetsFlutterBinding.ensureInitialized();
  // init Hive and open all boxes
  await Init.setupLocalHiveDatabase();

  runApp(MyApp());


  static setupLocalHiveDatabase() async 
    print('Setting up hive ...');
    var appDocDir = await getApplicationDocumentsDirectory();
    print('The application directory is: $appDocDir.path');
    _setupHive(appDocDir.path);
    print('Open all boxes ...');
    await Hive.openBox<CreditCard>(HiveBoxes.creditCard,
        compactionStrategy: (entries, deletedEntries) => deletedEntries > 10);
    await Hive.openBox<ConfigItem>(HiveBoxes.appConfig,
        compactionStrategy: (entries, deletedEntries) => deletedEntries > 10);
    await Hive.openBox<SupplierOverview>(HiveBoxes.supplier,
        compactionStrategy: (entries, deletedEntries) => deletedEntries > 20);
    await Hive.openBox<SubscriptionOverview>(HiveBoxes.subscription,
        compactionStrategy: (entries, deletedEntries) => deletedEntries > 20);
    await Hive.openBox<BscUserProfile>(HiveBoxes.bscUserProfile,
        compactionStrategy: (entries, deletedEntries) => deletedEntries > 10);
    await Hive.openBox<SyncJob>(HiveBoxes.syncJob,
        compactionStrategy: (entries, deletedEntries) => deletedEntries > 10);
    await Hive.openBox<SyncProtocol>(HiveBoxes.syncProtocol,
        compactionStrategy: (entries, deletedEntries) => deletedEntries > 20);
    await Hive.openBox<ClientDevice>(HiveBoxes.clientDevice,
        compactionStrategy: (entries, deletedEntries) => deletedEntries > 2);
    await Hive.openBox<ClientError>(HiveBoxes.clientError,
        compactionStrategy: (entries, deletedEntries) => deletedEntries > 10);

    print('done.');
  


  static void _setupHive(String path) async 
    // We initialize Hive and we give it the current path
    print('Initializing Hive databases ...');
    //Hive.init(path);
    await Hive.initFlutter(path);
    print('Registering Hive Adapters...');
    Hive.registerAdapter(ConfigItemAdapter()); // ID 1
    Hive.registerAdapter(CreditCardAdapter()); // ID 2
    Hive.registerAdapter(SubscriptionOverviewAdapter()); // ID 3
    Hive.registerAdapter(SupplierOverviewAdapter()); // ID 4
    Hive.registerAdapter(ClientErrorAdapter()); // ID 5
    Hive.registerAdapter(BscUserProfileAdapter()); //ID 6
    Hive.registerAdapter(SyncJobAdapter()); //ID 7
    Hive.registerAdapter(PersonAdapter()); // ID 8
    Hive.registerAdapter(ContactDataAdapter()); // ID 9
    Hive.registerAdapter(SyncProtocolAdapter()); // ID 10
    Hive.registerAdapter(ClientDeviceAdapter()); // ID 11

    // Enum Types
    Hive.registerAdapter(SyncStatesAdapter()); // ID 101
    Hive.registerAdapter(SyncDirectionsAdapter()); // ID 102
    Hive.registerAdapter(ContractDataObjectTypesAdapter()); // ID 103
    Hive.registerAdapter(OperationResultsAdapter()); // ID 104
    Hive.registerAdapter(PlatformTypesAdapter()); // ID 106

    print('Done with Hive setup.');
  

    数据未正确保存

我有一个奇怪的情况,应用程序重启(热重载或完全重启)后数据为空。这是保存对象后的输出

flutter: UserData: BscUserProfile(0031cd3c-5851-403c-9c11-7ea190db5abf, Debug Test User, debug@test.com, , , [])

如果我进行热重载,数据如下所示:

flutter: UserData: BscUserProfile(, , , , , [])

对象在数据库中,但为空

这是飞镖代码(它在上面的Init类中)

  static _setupUser(String userEmail) async 
    var userBox = Hive.box<BscUserProfile>(HiveBoxes.bscUserProfile);
    //await userBox.deleteAll(userBox.keys);
    if (userBox.isEmpty) 
      // create a fake user for testing
      var user = BscUserProfile(
        bscUserEmail: userEmail,
        bscUserDisplayName: 'Debug Test User',
        bscUserId: Uuid().v4().toString(),
      );
      await userBox.put(user.bscUserId, user);
      GetIt.instance.registerSingleton(user);
      for (var user in userBox.values) 
        print('UserData: $user.toString()');
      

      return;
    
    // dump database
    for (var user in userBox.values) 
      print('UserData: $user.toString()');
    
    var user = userBox.values.firstWhereOrNull((user) => user.bscUserEmail == userEmail);
    if (user != null) 
      GetIt.instance.registerSingleton(user);
      return;
    
  

如果我取消注释第二行以删除框中的所有对象,它会正确跳转到(userBox.isEmpty),然后显示正确的数据。重新加载后数据库not Empty而是显示空对象!

3。更新不起作用 第三个问题也在Init 类中。当应用程序启动时,我会保留一些设备特定的数据。更新后,应用程序重新启动后,更新不反映在数据库中。这里是一些打印语句的输出:

flutter: ClientDevice(e5634285-7e46-4eed-8d89-1a9b4cbfb94d, 93C259F6-EBE2-4079-9B99-E542B714B230, iPhone 11 Pro, iPhone, PlatformTypes.ios, ios, 11.6, 16, en, gala.local, false, 172.16.63.186)
flutter: Device has changed!
flutter: Current device: ClientDevice(e5634285-7e46-4eed-8d89-1a9b4cbfb94d, 93C259F6-EBE2-4079-9B99-E542B714B230, iPhone 11 Pro, iPhone, PlatformTypes.iOS, iOS, 15.0, 16, en, gala.local, false, 172.16.63.186)
flutter: Persisted device: ClientDevice(e5634285-7e46-4eed-8d89-1a9b4cbfb94d, 93C259F6-EBE2-4079-9B99-E542B714B230, iPhone 11 Pro, iPhone, PlatformTypes.iOS, ios, 11.6, 16, en, gala.local, false, 172.16.63.186)

这里 Version 没有更新:11.6 重启后显示,然后更新为 15.0 但似乎没有持久化.

我不知道我在这里做错了什么,或者在初始化期间更改数据是否有问题,或者是Future / async 问题。它很好奇。如果有人看到出了什么问题,将不胜感激。 (我使用 androidStudio 和最新版本的 Dart 和 Flutter)

【问题讨论】:

【参考方案1】:

在没有路径的情况下在 main 中调用它

喜欢

/// main
void main() async 
  /// db init
  await Hive.initFlutter();
....

我认为你可以使用你的调用结构,但你需要 init Hive.initFlutter() 没有路径

【讨论】:

问题 1) 似乎在我将 Hive.initFlutter() 写为我的 main() 方法的第一行时得到了解决。不知道有什么区别,因为如消息中所述,我在Init 类中尝试了 withwithout 路径参数。 问题 2. 和 3. 仍然存在. 已解决问题 2):BsUserProfileCode 类中有旧代码,`@HiveField(0)` 数字混乱且部分缺失。更正它们后,它按预期工作。

以上是关于Flutter 和 Hive 的奇怪问题的主要内容,如果未能解决你的问题,请参考以下文章

flutte学习-编译模式

flutte学习-编译模式

Flutter 离线数据方案 Flutter_Data 包

Flutter 离线数据方案 Flutter_Data 包

flutte的第一个hello world程序

Flutter & Hive - 如何在 Hive 中保存重新排序的列表