1

I'm trying to make a method to add entries in a Hive box but after adding my id key is always null. now I know I can change the key at onPressed() by:

 getIt<TodoDatasource>().addTodo(Todo(
                        id: 0,  // <----------------------------- IN QUESTION
                        name: _controlName.text,
                        description: _controlDescription.text,
                        completed: 0, // default
                      ));

but doing this will affect the id on my other data sources, SQFLite(which can assign an auto-increment at the id column), and Firebase RTDB(which generates an id for each entry).

what I noticed as well is Hive is also generating an auto-increment on each entry AND based on this GitHub post "click me!", the .add() method returns an int. that's not the case as on my project this returns a Future so can't seem to use that to match my id. is there a solution or a workaround for this problem?

here's the necessary code blocks:

DataServiceManager class

import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:todo_list1/local_hive_datasource.dart';
import 'package:todo_list1/local_sqlite_datasource.dart';
import 'package:todo_list1/services/todo_datasource.dart';
import 'package:todo_list1/remote_api_datasource.dart';

import 'dart:io' show Platform;
import '../models/todo.dart';

class DataServiceManager implements TodoDatasource {
  late final TodoDatasource _local;
  final TodoDatasource _remote = RemoteApiDatasource();

  DataServiceManager() {
    // if (kIsWeb) {
    //   _local = LocalHiveDatasource();
    // } else {
    //   _local = LocalSQLiteDatasource();
    // }
    _local = LocalHiveDatasource();
  }

  Future<bool> _checkConnectivity() async {
    if (!Platform.isAndroid ||
        !Platform.isWindows ||
        !Platform.isFuchsia ||
        !Platform.isIOS ||
        !Platform.isLinux ||
        !Platform.isMacOS) {
      if (kIsWeb &&
          await Connectivity().checkConnectivity() == ConnectivityResult.none) {
        return false;
      }
    }
    return true;
  }

  @override
  Future<bool> addTodo(Todo t) async {
    // return await _checkConnectivity()
    //     ? await _remote.addTodo(t)
    //     : await _local.addTodo(t);
    return _local.addTodo(t);
  }

  @override
  Future<bool> updateTodo(Todo t) async {
    // return await _checkConnectivity()
    //     ? await _remote.updateTodo(t)
    //     : await _local.updateTodo(t);
    return _local.updateTodo(t);
  }

  @override
  Future<bool> deleteTodo(Todo t) async {
    // return await _checkConnectivity()
    //     ? await _remote.deleteTodo(t)
    //     : await _local.deleteTodo(t);
    return _local.deleteTodo(t);
  }

  @override
  Future<List<Todo>> getAllTodo() async {
    // return await _checkConnectivity()
    //     ? await _remote.getAllTodo()
    //     : await _local.getAllTodo();
    return _local.getAllTodo();
  }

  @override
  Future<List<Map<String, Object?>>> getId(int i) {
    // return await _checkConnectivity()
    //     ? await _remote.getAllTodo()
    //     : await _local.getAllTodo();
    return _local.getId(i);
  }
}

LocalHiveDatasource class

import 'package:hive_flutter/hive_flutter.dart';

import 'package:todo_list1/models/todo.dart';
import 'package:todo_list1/services/todo_datasource.dart';

class LocalHiveDatasource implements TodoDatasource {
  bool initialised = false;
  int _id = 0; // <----------------------------my workaround

  LocalHiveDatasource() {
    init();
  }

  Future<void> init() async {
    await Hive.initFlutter();
    Hive.registerAdapter(TodoAdapter());
    await Hive.openBox('todos_box');
    initialised = true;
  }

  @override
  Future<bool> addTodo(Todo t) async {

    // MY WORKAROUND
    // can add before pushing to the box but when the app exits,
    // the _id rolls back to 0
    // therefore the instance of entry will not match the id...
    if (t.id == null) {
      _id++;
      t.id = _id;
    }

    // conversion of todos model to map
    final Map<String, dynamic> todoToMap = t.toMap();
    final box = await Hive.openBox('todos_box');
    box.add(todoToMap);
    await box.close();
    return true;
  }

  @override
  Future<bool> deleteTodo(Todo t) async {
    throw UnimplementedError();
  }

  @override
  Future<List<Todo>> getAllTodo() async {
    if (!initialised) return <Todo>[];

    //   opens the box
    Box box = await Hive.openBox('todos_box');

    Map<dynamic, dynamic> retrievedMapdData = box.toMap();

    box.close();

    return List.generate(retrievedMapdData.length, (index) {
      return Todo(
        id: retrievedMapdData[index]['id'],
        name: retrievedMapdData[index]['name'],
        description: retrievedMapdData[index]['description'],
        completed: retrievedMapdData[index]['completed'],
      );
    });
  }

  @override
  Future<List<Map<String, Object?>>> getId(int i) async {
   throw UnimplementedError();
  }

  @override
  Future<bool> updateTodo(Todo t) async {
   
    throw UnimplementedError();
  }
}

0 Answers0