getting an error of register adapter in flutter using hive - flutter

I have created a simple app for storing data using hive and getx as state management
I have followed all the steps but even thought its showing an error like
After coding when I played ...it worked fine...but when I restart the app...it stops showing white background and an error in console....
have u forgotten register adapter...
I have registered adapter in main...eventhough getting this error
error is
Unhandled Exception: HiveError: Cannot read, unknown typeId: 32. Did you forget to register an adapter?
class TransactionController extends GetxController
{
List<TransactionModel> _transactions=[];
Box<TransactionModel> transactionbox=Hive.box('a');
List<TransactionModel> get transactions{
return _transactions;
}
TransactionController(){
_transactions=[];
for(int x=0;x<transactionbox.values.length;x++)
{
var trns=transactionbox.getAt(x);
if(trns!=null)
_transactions.add(trns);
}
}
int get countlength{
return _transactions.length;
}
void addTransaction(TransactionModel transaction)
{
_transactions.add(transaction);
transactionbox.add(transaction);
update();
}
}
this is model class
import 'package:hive_flutter/hive_flutter.dart';
import 'package:hive/hive.dart';
part 'transactionmodel.g.dart';
#HiveType(typeId: 0)
class TransactionModel
{
#HiveField(0)
String id;
#HiveField(1)
String detail;
#HiveField(2)
bool isExpense;
TransactionModel({
required this.id,
required this.detail,
required this.isExpense,
});
}
this is void main
void main() async
{
WidgetsFlutterBinding.ensureInitialized();
Directory dir=await getApplicationDocumentsDirectory();
await Hive.initFlutter(dir.path);
await Hive.openBox<TransactionModel>('a');
Hive.registerAdapter<TransactionModel>(TransactionModelAdapter());
runApp(MyApp());
}

I see a wrong thing in your code, you're trying to open the Hive box before registering the adapter, you're calling Hive.registerAdapter after you already opened the box, change it with this:
void main() async
{
WidgetsFlutterBinding.ensureInitialized();
Directory dir=await getApplicationDocumentsDirectory();
await Hive.initFlutter(dir.path);
Hive.registerAdapter<TransactionModel>(TransactionModelAdapter()); // this should be first
await Hive.openBox<TransactionModel>('a'); // then this
runApp(MyApp());
}

Related

HiveError: Box not found error on hot restart or build in Flutter

I have this code which starts the app build in error but when hot reloaded app works again if I hot restart error occurs again .I have initialized the Box and app works just fine after hot reload but not hot restart or if built in debug mode.
main
void main() async {
await Hive.initFlutter();
Hive.openBox('mybox');
runApp(MyApp());
}
HomePage.dart
class _HomePageState extends State<HomePage> {
final _myBox = Hive.box('mybox');
void writeData() {
if (_keyText.text.isEmpty || _valueText.text.isEmpty) {
if (_keyText.text.isEmpty) {
result = 'Key cannot be null';
_keyTextNode.requestFocus();
} else {
result = 'Value cannot be null';
_valueTextNode.requestFocus();
}
} else {
_myBox.put(_keyText.text, _valueText.text);
result =
'${_keyText.text} : ${_valueText.text} has been saved to HiveBox';
emptyTextFields();
}
setState(() {
result = result;
});
}
the openBox is asynchronous, you need to wait for the box until it's opened before you use it, add await:
void main() async {
await Hive.initFlutter();
await Hive.openBox('mybox'); // add await
runApp(MyApp());
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();//add this line to
//ensure Initialized
await Hive.initFlutter();
await Hive.openBox('mybox');
runApp(MyApp());
}
WidgetsFlutterBinding

dart asyncronous code - should i choose static or non static parameter?

i was building an app with Flutter and Firebase and I encountered the following problem:
I have a firebase helper class with within all the methods I need to use firebase realtime database and I will call these from the main function.
this is the firebase helper class:
class FBHelper {
FBHelper._internal();
static final DatabaseReference database = FirebaseDatabase.instance.ref('/');
factory FBHelper() {
return FBHelper._internal();
}
Future<void> initializeFirebase() async {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
print('firebase app initialized');
}
Future<void> callPost(dynamic o) async {
await database.set(o);
}
}
and this is my main
void main() async {
final _ = FBHelper();
WidgetsFlutterBinding.ensureInitialized();
await _.initializeFirebase();
await _.callPost({"master": "1"});
runApp(const MyApp());
}
if I mark as static the DatabaseReference database property there are no problems at all.
instead, if I avoid the static modifier I get this
FirebaseException ([core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp())
can someone explain me what I’m missing? do I have a wrong idea of how to use static?

Flutter - How to add and retrieve data to/from hive?

I know it sounds simple and I went through the example given in the documentation. Yet somehow I am unable to get it right.
This is what I have:
void main() async {
await Hive.initFlutter();
//Hive.openBox('workoutBox');
runApp(const MyApp());
}
...
Next Screen:
var box;
...
Trying to add to the box
Future<void> _save() async{
// save doc id somewhere
final Id = doc.id;
//box = await Hive.openBox('workoutBox');
box.put("Id", Id);
}
Trying to retrieve in another function:
var someId = box.get("Id");
Current error: get was called on null
My confusion is, where/how do you declare, open and retrieve from the box in this situation?
It seems you are forgetting to initialize a Box param and assign the value returned by the openBox function to it.
After Hive initialization you should have something like this:
Box<myValue> boxValue = await Hive.openBox("myKey");
Important: the retrieval method will dependend based on what you need to do and, more importantly, how you saved your data in the first place.
Let's say you saved data like this:
await boxValue.add(value);
By adding data like this, the key assigned to the value will be an auto-incremented one, so that trying to retrieve it with a specific key that never was assigned in the first place will fail.
If you did add the data like this:
await boxValue.put("myKey", value);
then you will be able to successfully fetch it using the intended key.
You can do the following:
void main() async {
await Hive.initFlutter();
await Hive.openBox('workoutBox'); //<- make sure you await this
runApp(const MyApp());
}
...
_save() { // <- can be a synchronous function
final box = Hive.box('workoutBox'); //<- get an already opened box, no await necessary here
// save doc id somewhere
final Id = doc.id;
box.put("Id", Id);
}
I have written an example app and a Flutter Cubits + Hooks + Hive DB tutorial. I have the following AppDatabase class there:
const String _bookBox = 'book';
#Singleton()
class AppDatabase {
AppDatabase._constructor();
static final AppDatabase _instance = AppDatabase._constructor();
factory AppDatabase() => _instance;
late Box<BookDb> _booksBox;
Future<void> initialize() async {
await Hive.initFlutter();
Hive.registerAdapter<BookDb>(BookDbAdapter());
_booksBox = await Hive.openBox<BookDb>(_bookBox);
}
Future<void> saveBook(Book book) async {
await _booksBox.put(
book.id,
BookDb(
book.id,
book.title,
book.author,
book.publicationDate,
book.about,
book.readAlready,
));
}
Future<void> deleteBook(int id) async {
await _booksBox.delete(id);
}
...

Unit Testing hive abstraction layer

So I created a simpler level of abstraction to use Hive into my Flutter app. This should be the central point, where all hive boxes are administrated and accessed. Since e.g. getApplicationDocumentsDirectory is not available during testing, how can I still manage to test this whole file?
import '../services/workout.dart';
import 'package:hive/hive.dart';
import 'package:path_provider/path_provider.dart' as path_rovider;
import 'workout.dart';
class HiveService {
static final HiveService _singleton = HiveService._internal();
static const String _workoutBox = "workoutBox";
factory HiveService() {
return _singleton;
}
HiveService._internal();
static Future<void> init() async {
final appDocumentDirectory =
await path_rovider.getApplicationDocumentsDirectory();
Hive.init(appDocumentDirectory.path);
Hive.registerAdapter(WorkoutAdapter());
}
static Future openWorkouts() {
return Hive.openBox<Workout>(_workoutBox);
}
static Future close() {
return Hive.close();
}
}
First thing first, you need to initial Hive at the top of the main method in your test file, and then you can proceed with the rest of the tests.
You can use it in this way:
void initHive() {
var path = Directory.current.path;
Hive.init(path + '/test/hive_testing_path');
}
main() {
initHive();
//The rest of your test code.
}

Box not found. Did you forget to call Hive.openBox()?

When working with HIVE database in flutter. If you ever get error like this:
"Box not found. Did you forget to call Hive.openBox()?"
It means you haven't opened your box to
To resolve this issue call
await Hive.openBox("boxname");
before using the box
It means you haven't opened your box. To resolve this issue call
await Hive.openBox("boxname");
before using the box.
The box needs to be open either at the beginning, after database initialization or right before doing the operation on the box.
For example in my AppDatabase class I have only one box ('book') and I open it up in the initialize() method, like below:
The whole application and tutorial is here.
const String _bookBox = 'book';
#Singleton()
class AppDatabase {
AppDatabase._constructor();
static final AppDatabase _instance = AppDatabase._constructor();
factory AppDatabase() => _instance;
late Box<BookDb> _booksBox;
Future<void> initialize() async {
await Hive.initFlutter();
Hive.registerAdapter<BookDb>(BookDbAdapter());
_booksBox = await Hive.openBox<BookDb>(_bookBox);
}
Future<void> saveBook(Book book) async {
await _booksBox.put(
book.id,
BookDb(
book.id,
book.title,
book.author,
book.publicationDate,
book.about,
book.readAlready,
));
}
Future<void> deleteBook(int id) async {
await _booksBox.delete(id);
}
Future<void> deleteAllBooks() async {
await _booksBox.clear();
}
}
You have to open the box you want to use and make sure to use await while using the openBox() function.
await Hive.openBox("boxname");