isar / hive

Lightweight and blazing fast key-value database written in pure Dart.
Apache License 2.0
4.1k stars 407 forks source link

HiveList relationships are not updated properly #902

Open eli1stark opened 2 years ago

eli1stark commented 2 years ago

After updating an object in the box that is used in the hive list of other objects, it will be removed from the hive list until I make a Hot Restart of the app. The expected result if I update the object then it will be updated in HiveList of other objects.

import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:path_provider/path_provider.dart';

part 'reproducible_example.g.dart';

/// Instructions:
/// 1. Run main()
/// 2. Press "Add a new user"
/// 3. Make Hot Reload
/// 4. You now have: Bob[Instance of 'Friend]
/// 5. Press "Update a friend"
/// 6. Make Hot Reload
/// 7. "Bob[Instance of 'Friend]" will become "Bob[]"
///    "Friend" will become "New Friend"
///
/// Expected result:
/// "Bob[Instance of 'Friend']" will become "Bob[Instance of 'Friend']"
/// "Friend" will become "New Friend"
///
/// Notes:
/// If you make a hot restart of the app everything works as expected.
/// But it should work without hot restart.
///
/// Packages:
/// 1. hive: ^2.0.5
/// 2. hive_flutter: ^1.1.0
/// 3. hive_generator: ^1.1.2
/// 4. build_runner: ^2.1.7

final userBox = Hive.box<User>('users');
final friendBox = Hive.box<Friend>('friends');

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final directory = await getApplicationDocumentsDirectory();
  Hive.init(directory.path);
  Hive.registerAdapter(UserAdapter());
  Hive.registerAdapter(FriendAdapter());
  await Hive.openBox<User>('users');
  await Hive.openBox<Friend>('friends');
  if (friendBox.isEmpty) {
    await friendBox.add(Friend('Friend'));
  }
  runApp(const Home());
}

@HiveType(typeId: 0)
class User extends HiveObject {
  User(this.name, this.friends);

  @HiveField(0)
  final String name;
  @HiveField(1)
  final HiveList<Friend> friends;
}

@HiveType(typeId: 1)
class Friend extends HiveObject {
  Friend(this.name);

  @HiveField(0)
  final String name;
}

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Row(),
            const Text('Users:'),
            ...userBox.values.map((user) {
              return Text(user.name + user.friends.toString());
            }).toList(),
            const Text('Friends:'),
            ...friendBox.values.map((friend) {
              return Text(friend.name);
            }).toList(),
            TextButton(
              onPressed: () {
                final friends = HiveList<Friend>(
                  friendBox,
                  objects: [friendBox.values.first],
                );

                userBox.add(
                  User('Bob', friends),
                );
              },
              child: const Text('Add a new user'),
            ),
            TextButton(
              onPressed: () {
                friendBox.put(0, Friend('New Friend'));
              },
              child: const Text('Update a friend'),
            ),
          ],
        ),
      ),
    );
  }
}
sam-parks-singlemind commented 1 year ago

@eli1stark Did you ever find a workaround for this?

eli1stark commented 1 year ago

No, I recommend using objectbox instead. This library is hardly maintained these days and has a lot of issues.