hive icon indicating copy to clipboard operation
hive copied to clipboard

After updating HiveObject its key will become null

Open eli1stark opened this issue 3 years ago • 1 comments

I think it's a bug, why is the key changing to null if it's must be constant? But I want to say that the key is not changing internally in the hive box, it's still the same, but HiveObject for some reason holds null after the update, in order to fix this I need to hot restart my app.

Reproducible code example with dependencies is provided below:

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

part 'main.g.dart';

// dependencies:
// hive: ^2.0.5
// hive_flutter: ^1.1.0
// path_provider: ^2.0.8
// build_runner: ^2.1.7
// hive_generator: ^1.1.2

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final directory = await getApplicationDocumentsDirectory();

  Hive.init(directory.path);

  Hive.registerAdapter(MyModelAdapter());

  await Hive.openBox<MyModel>('my_model');

  Hive.box<MyModel>('my_model').add(MyModel('Test'));

  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late MyModel test;

  @override
  void initState() {
    test = Hive.box<MyModel>('my_model').values.first;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Row(),
            // 2. Check how key will become null
            // Accepted behaviour: key must not be null 
            Text(
              'Model ${test.name} Key: ${test.key}',
            ),
            // 1. Tap this button
            TextButton(
              onPressed: () {
                Hive.box<MyModel>('my_model').put(
                  test.key,
                  MyModel('Test ${DateTime.now().second}'),
                );
                setState(() {});
              },
              child: const Text('update'),
            ),
          ],
        ),
      ),
    );
  }
}

@HiveType(typeId: 0)
class MyModel extends HiveObject {
  MyModel(this.name);

  @HiveField(0)
  final String name;
}

eli1stark avatar Jan 23 '22 17:01 eli1stark

Similar is happening with my code. When I tried to update an item with put method , the key is null. Do you get any solution?

TheAlphaApp avatar May 21 '22 09:05 TheAlphaApp

I have the same problem, any news about this?

alexiswbr avatar Jan 11 '23 07:01 alexiswbr

It is probably null because you did not add @HiveField to the second adapter.

I can't comment because I can't see the model, but you should use a structure similar to this.

I think you probably forgot to use HiveField in class Geys extends HiveObject.

And You should add all adapters in main like this;

  Hive.registerAdapter(GGGAdapter());
  Hive.registerAdapter(GeysAdapter());
part 'denememodel.g.dart';

@HiveType(typeId: 0)
class GGG extends HiveObject {
  @HiveField(0)
  List<Geys>? geys;
  @HiveField(1)
  GGG({this.geys});

  GGG.fromJson(Map<String, dynamic> json) {
    if (json['geys'] != null) {
      geys = <Geys>[];
      json['geys'].forEach((v) {
        geys!.add(new Geys.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    if (this.geys != null) {
      data['geys'] = this.geys!.map((v) => v.toJson()).toList();
    }
    return data;
  }
}

@HiveType(typeId: 1)
class Geys extends HiveObject {
  @HiveField(0)
  String? id;
  @HiveField(1)
  String? author;

  Geys({this.id, this.author});

  Geys.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    author = json['author'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['id'] = this.id;
    data['author'] = this.author;
    return data;
  }
} `


seceba avatar Jan 11 '23 11:01 seceba

Similar is happening with my code, any solution?

salsabeela2 avatar Feb 18 '23 22:02 salsabeela2

I suppose this is simply because when a new object is being added into the hive database, the new object gets the key.

onPressed: () {
  int index = test.key;  // we store this because we will be assigning test to a new object, which doesn't have the key
  test = MyModel('Test ${DateTime.now().second}');  // assign test to a new object
  Hive.box<MyModel>('my_model').put(index, test);  // now the new object will have the key
  setState(() {});
}

In the previous example by @eli1stark , the temporary model created within the function is getting the key

in short, the key is binded with the actual object in the database, I believe

harryyan966 avatar Jun 20 '23 03:06 harryyan966