isar / hive

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

type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype<…> #260

Open mitty1987 opened 4 years ago

mitty1987 commented 4 years ago
Future<bool> saveTagVersion(List<TagVersion> data) async {
    Box<TagVersion> b = Hive.box<TagVersion>(hiveTagVersion);
//    b.deleteAll(b.keys);
    await b.clear();
    await b.addAll(data);
//    await b.compact();
    print(b.get(0));
    Box<TagVersion> b2 = Hive.box<TagVersion>(hiveTagVersion);
    print(b2.get(0));
    await b.close();
    await Hive.openBox<TagVersion>(hiveTagVersion);
    Box b3 = Hive.box<TagVersion>(hiveTagVersion);
    print(b3.keys);
    print(b3.values);

    return true;
  }

Steps to Reproduce b and b2 are all right, but b3.values or get will throw the exception after reopen box as TagVersion...

flutter: \^[[38;5;196m├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄<…>
flutter: \^[[38;5;196m│ ⛔ ══╡ EXCEPTION CAUGHT BY FLUTTER FRAMEWORK ╞══════════════════════<…>
flutter: \^[[38;5;196m│ ⛔ The following _CastError was thrown:<…>
flutter: \^[[38;5;196m│ ⛔ type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype<…>
flutter: \^[[38;5;196m│ ⛔ of type 'TagVersion' in type cast<…>
flutter: \^[[38;5;196m│ ⛔ <…>
flutter: \^[[38;5;196m│ ⛔ When the exception was thrown, this was the stack:<…>
flutter: \^[[38;5;196m│ ⛔ #0      Keystore.getValues.<anonymous closure> (package:hive/src/box/keystore.dart:122:45)<…>
flutter: \^[[38;5;196m│ ⛔ #1      MappedIterator.moveNext (dart:_internal/iterable.dart:395:18)<…>
flutter: \^[[38;5;196m│ ⛔ #2      _iterablePartsToStrings (dart:collection/iterable.dart:320:13)<…>
flutter: \^[[38;5;196m│ ⛔ #3      IterableBase.iterableToShortString (dart:collection/iterable.dart:240:7)<…>
flutter: \^[[38;5;196m│ ⛔ #4      Iterable.toString (dart:core/iterable.dart:669:37)<…>
flutter: \^[[38;5;196m│ ⛔ #5      _StringBase._interpolateSingle (dart:core-patch/string_patch.dart:826:17)<…>
flutter: \^[[38;5;196m│ ⛔ #6      print (dart:core/print.dart:11:26)<…>
flutter: \^[[38;5;196m│ ⛔ #7      MyHive.saveTagVersion (package:sign_pad/core/help/hbox.dart:88:5)<…>
flutter: \^[[38;5;196m│ ⛔ <asynchronous suspension><…>
flutter: \^[[38;5;196m│ ⛔ #8      SplashPresenterImpl.loadTagVersion.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:sign_pad/ui/splash/splash_presenter.dart:101:26)<…>
flutter: \^[[38;5;196m│ ⛔ #11     AsyncAction._runUnary (package:mobx/src/api/async/async_action.dart:57:29)<…>
flutter: \^[[38;5;196m│ ⛔ #19     MyHive.getTagVersion (package:sign_pad/core/help/hbox.dart)<…>
flutter: \^[[38;5;196m│ ⛔ #23     AsyncAction._runUnary (package:mobx/src/api/async/async_action.dart:57:29)<…>
flutter: \^[[38;5;196m│ ⛔ #31     BoxBaseImpl.clear (package:hive/src/box/box_base_impl.dart)<…>
flutter: \^[[38;5;196m│ ⛔ #35     AsyncAction._runUnary (package:mobx/src/api/async/async_action.dart:57:29)<…>
flutter: \^[[38;5;196m│ ⛔ #43     StorageBackendVm.clear.<anonymous closure> (package:hive/src/backend/vm/storage_backend_vm.dart)<…>
flutter: \^[[38;5;196m│ ⛔ #47     AsyncAction._runUnary (package:mobx/src/api/async/async_action.dart:57:29)<…>
flutter: \^[[38;5;196m│ ⛔ #56     AsyncAction._run (package:mobx/src/api/async/async_action.dart:44:29)<…>
flutter: \^[[38;5;196m│ ⛔ (elided 45 frames from package dart:async and package dart:async-patch)<…>
flutter: \^[[38;5;196m│ ⛔ ═════════════════════════════════════════════════════════════════<…>
flutter: \^[[38;5;196m│ ⛔ <…>
flutter: \^[[38;5;196m└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────<…>

Version

mitty1987 commented 4 years ago

I found the reason. Because of the use of serializable, I need extends $tagversionserializable, and $tagversionserializable extends map, which causes typeadapter < tagversion > to fail, so I modify the method BinaryWriterImpl.write,

void write<T>(T value, {bool writeTypeId = true}) {
    if (value == null) {
      if (writeTypeId) {
        writeByte(FrameValueType.nullT);
      }
      return;
    } 
    var resolved = _typeRegistry.findAdapterForValue(value);
    if (resolved != null) {
      if (writeTypeId) {
        writeByte(resolved.typeId);
      }
      resolved.adapter.write(this, value);
    } else if (value is int) {
      if (writeTypeId) {
        writeByte(FrameValueType.intT);
      }
      writeInt(value);
    } else if (value is double) {
      if (writeTypeId) {
        writeByte(FrameValueType.doubleT);
      }
      writeDouble(value);
    } else if (value is bool) {
      if (writeTypeId) {
        writeByte(FrameValueType.boolT);
      }
      writeBool(value);
    } else if (value is String) {
      if (writeTypeId) {
        writeByte(FrameValueType.stringT);
      }
      writeString(value);
    } else if (value is List) {
      _writeList(value, writeTypeId: writeTypeId);
    } else if (value is Map) {
      if (writeTypeId) {
        writeByte(FrameValueType.mapT);
      }
      writeMap(value);
    } else {
      throw HiveError('Cannot write, unknown type: ${value.runtimeType}. '
            'Did you forget to register an adapter?');
    }
  }

First check Adapter...

dop3ch3f commented 4 years ago

IMHO dart does this thing where during execution it generates an InternalLinkedHashMap. So be sure to call a .toMap() wherever it throws the error to convert it to a map. This should be a temporary fix to the problem

mitty1987 commented 3 years ago

image Maybe check Adapter should be at first when write to db Hive version: 2.0.0