Facing an error in retrieving or opening the Hive Box in Flutter app

51 views Asked by At

So as a part of project i am trying to create a Hive database which can store the following details of a user's transaction (all except 2 the user will input)

  1. _userID (uid generated by firebase)
  2. amount (value of transaction - user)
  3. type (Selected value from dropdown box - user)
  4. categoryValue (Selected value from dropdown box - user)
  5. DescriptionValue (String given by user)
  6. DateTime (DateTime.now())

the code associated is as follows

OutlinedButton(
  onPressed: () {
     saveTransaction(
       _userID,
       amount,
       type,
       categoryValue,
       descriptionValue,
       DateTime.now(),
     );
                 

This is the relevant code defined in a separate dart file

void main() async {
  await Hive.initFlutter();
  Hive.registerAdapter(TransactionModelAdapter());
}

void saveTransaction(String userId, double amount, String type, String category, String description, DateTime dateTime) async {
  // Open the Hive box for transactions
  final transactionsBox = await Hive.openBox<TransactionModel>('transactions');

  // Create a new transaction object
  final transaction = TransactionModel()
    ..userId = userId
    ..amount = amount
    ..type = type
    ..category = category
    ..description = description
    ..dateTime = dateTime;

  // Save the transaction to the box
  await transactionsBox.add(transaction);
}

the following is the box model in a seraparate dart file

import 'package:hive/hive.dart';

part 'transaction_model.g.dart'; // Generated file name

@HiveType(typeId: 0) // HiveType annotation with typeId
class TransactionModel extends HiveObject {
  @HiveField(0) // HiveField annotation with index
  late String userId; // Unique user ID associated with the transaction

  @HiveField(1) // HiveField annotation with index
  late double amount;

  @HiveField(2)
  late String type; // Type of transaction (e.g., expense, income)

  @HiveField(3)
  late String category; // Category of the transaction

  @HiveField(4)
  late String description; // Description of the transaction

  @HiveField(5)
  late DateTime dateTime; // Date and time of the transaction
}

and now finally the implementation where error is being shown

void main() async {
  runApp(transactionApp());
  Hive.registerAdapter(TransactionModelAdapter());
  await Hive.initFlutter();
}

class transactionApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: AllTransactionsPage(),
    );
  }
}

class AllTransactionsPage extends StatefulWidget {
  @override
  _AllTransactionsPageState createState() => _AllTransactionsPageState();
}

class _AllTransactionsPageState extends State<AllTransactionsPage> {
  late Box<TransactionModel> transact_box;

  @override
  void initState() {
    super.initState();
    _openBox();
  }

  Future<void> _openBox() async {
    transact_box = await Hive.openBox<TransactionModel>('transactions');
    setState(() {}); // Trigger rebuild after box is initialized
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('All Transactions Page'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // Button onPressed action
            print('Button Pressed');
            print("Number of entries are ${transact_box.length}");
          },
          child: Text('Press Me'),
        ),
      ),
    );
  }
}

This above code was written to check if the entries are being added to the box as desired.

I am getting the following error message when i click the button

error message

1

There are 1 answers

0
聂超群 On
transact_box = await Hive.openBox<TransactionModel>('transactions');

transact_box's initialization may need some time since it's a async operation, which means when you access transact_box, it may not be initialized yet.

Dart offers no way to tell if a late variable has been initialized or assigned to. If you access it, it either immediately runs the initializer (if it has one) or throws an exception.

A possible solution is wrap transact_box access with try catch:

try {
  print("Number of entries are ${transact_box.length}");
} on Exception catch (e) {
  print("transact_box not initialized");
}

The best solution is refine your logic. You must guarantee transact_box is initialized before you access it.