Closed Abhilash-Chandran closed 3 years ago
@Abhilash-Chandran You marked id
as final
... Remove final
and it will work ...
@RTrackerDev thanks for your quick feedback. I will check this. But final field serves the purpose that this custom ID is not manipulated anywhere else. I am not clear why final fields can't be queried. I assume it has to do with the generated code then.
Final fields can't be currently set because of the way objects are constructed in the generated code when read from the database. Let's see what we can do about that
@Abhilash-Chandran Yes the whole reason is in the code that is generated. You could look on objectbox.g.dart
file
@vaind maybe you could use entity data class constructor, when generate code?
maybe you could use entity data class constructor, when generate code?
Yes, but now that I've had a proper look at the class definition, ObjectBox is actually doing the only possible thing...
@Abhilash-Chandran - For ObjectBox to be able to load the id
(the one you initialize to Uuid().v4()
) field from the database, it needs to set it somehow on the constructed object. Your only constructor doesn't accept the field and it's marked final, so it can't even be set after the object is constructed. Therefore, any time ObjectBox reads the ToDo
object from the database, the (only) constructor you've provided initializes with a new UUID.
ToDo({
@required this.description,
this.dueDate,
this.completed = false,
@required this.userId,
}) : id = Uuid().v4(); // Initializes id with a unique value.
To understand what's happening, see the code in objectbox.g.dart
, more specifically look for objectFromFB
To actually do something about this, your constructor would need to look for example like this, i.e. provide an option to specify the id
or it's generated.
ToDo({
this.id = Uuid().v4(),
@required this.description,
this.dueDate,
this.completed = false,
@required this.userId,
})
Then, we could modify the code generator to recognize this use case (final fields initialized in a constructor) and construct the object appropriately.
@Abhilash-Chandran - For ObjectBox to be able to load the
id
(the one you initialize toUuid().v4()
) field from the database, it needs to set it somehow on the constructed object. Your only constructor doesn't accept the field and it's marked final, so it can't even be set after the object is constructed. Therefore, any time ObjectBox reads theToDo
object from the database, the (only) constructor you've provided initializes with a new UUID.
Thanks for pointing this out. I guess this could be an issue even while de-serializing using HIVE.
To understand what's happening, see the code in
objectbox.g.dart
, more specifically look forobjectFromFB
I looked into this and realized flatbuffers are used internally. Now this is no more a black box for me. 😃
To actually do something about this, your constructor would need to look for example like this, i.e. provide an option to specify the
id
or it's generated.ToDo({ this.id = Uuid().v4(), @required this.description, this.dueDate, this.completed = false, @required this.userId, })
I will try to change the constructors accordingly. My current approach is clearly invalid. 😐
BTW. If it helps in anyway following is the repo I am working on. Basically I am trying to create a ToDo app demo for flutter_command
package using different types store as backend.
This is the repo. https://github.com/Abhilash-Chandran/flutter_command_todo
Update: recent code generation changes (0.13.0-nullsafety.0 prerelease) now try to use a constructor if available, so maybe give it a try.
Update: recent code generation changes (0.13.0-nullsafety.0 prerelease) now try to use a constructor if available, so maybe give it a try.
Oh Cool.. Thanks a lot for the heads up. Will check and let you know..
A note from a separate SO issue - to keep in mind when looking into this. This is why a user had to create bridge classes and do conversions:
Regarding the question about Bridge class , since I made my Event class by extending the Equatable and all the properties are defined as
final
https://stackoverflow.com/questions/67013723/flutter-objectbox-performance-issue/67017621?noredirect=1#comment118509013_67017621
Description The scenario is adapting an existing model class to be compatible with ObjectBox. Assume the following
ToDo.dart
file which represents the model ofToDo
item. Existing model already uses the reserved keywordid
as aString id
for another form of backend store such as Hive or InMemory list. Now to adapt this model to be compatible with ObjectBox terminology, I created a new field calledoboxId
with the@Id
annottation.ToDo.dart
Basic info (please complete the following information):
To Reproduce Steps to reproduce the behavior:
ToDo.dart
as model class.flutter pub run build_runner build
Expected behavior It is expected that the
id
field is still available for querying as it is required to fulfill already existing contracts in the code base.Additional Information
pubspec.yaml
```yml name: flutter_command_todo description: A new Flutter project. publish_to: "none" version: 1.0.0+1 environment: sdk: ">=2.7.0 <3.0.0" dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.2 flutter_command: ^0.9.3 get_it: ^5.0.6 uuid: ^2.2.2 objectbox: ^0.11.0 objectbox_flutter_libs: any dev_dependencies: flutter_test: sdk: flutter build_runner: objectbox_generator: any flutter: uses-material-design: true ```Flutter information
flutter doctor
Doctor summary (to see all details, run flutter doctor -v): [√] Flutter (Channel beta, 1.25.0-8.1.pre, on Microsoft Windows [Version 10.0.18363.1316], locale de-DE) [√] Android toolchain - develop for Android devices (Android SDK version 29.0.3) [√] Chrome - develop for the web [√] Android Studio (version 4.1.0) [√] VS Code (version 1.53.2) [√] Connected device (1 available) • No issues found!