Articles in this section
Category / Section

How to load data to Flutter DataTable (SfDataGrid) with Hive box?

7 mins read

Load the data from the hive database to the Flutter DataTable widget by fetching the list collection from the hive database, and create the rows for the Datagrid from that list collection.

The following steps explain how to load the data from the hive database to the Flutter DataTable.

STEP 1: To access the hive database, add the following dependencies in pubspec.yaml.

dependencies:
  hive_flutter: ^1.0.0
  get: ^4.1.3
  flutter_secure_storage: ^3.3.5
  hive: ^2.0.0
  path_provider: ^2.0.1
 
dev_dependencies:
  hive_generator: ^1.0.0
  build_runner: ^1.11.5

 

STEP 2: Import the following libraries in the Flutter application. 

import 'dart:convert';
import 'package:get/get.dart';
import 'package:hive/hive.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';

 

STEP 3: Create the class with the required properties that are given in the hive database, and add proper hive annotations for generating type adaptors. Here, we have explained with simple Employee class.

import 'package:hive/hive.dart';
 
@HiveType(typeId: 0)
class Employee {
  @HiveField(0)
  int id;
  @HiveField(1)
  String name;
  @HiveField(2)
  String designation;
  @HiveField(3)
  int salary;
 
  Employee(
    this.id,
    this.name,
    this.designation,
    this.salary,
  );
}

 

 

STEP 4:  Create a hive database. Open the hive box before performing any operation in the database. Open the hive box using Hive.openBox (‘DataBase name’) method. Here we have created a hive database for fetching data from the database, and performing CRUD operation.

class EmployeeDatabase extends GetxController {
  String boxName = 'employee_database';
 
  List<Employee> employeeList = [];
 
 
  Future<Box<Employee>> encryptedBox() async {
    final FlutterSecureStorage secureStorage = const FlutterSecureStorage();
    var containsEncryptionKey = await secureStorage.containsKey(key: 'key');
    if (!containsEncryptionKey) {
      var key = Hive.generateSecureKey();
      await secureStorage.write(key: 'key', value: base64UrlEncode(key));
    }
    var encryptionKey = base64Url.decode(await secureStorage.read(key: 'key'));
    var box = await Hive.openBox<Employee>(boxName,
        encryptionCipher: HiveAesCipher(encryptionKey));
    return box;
  }
 
void loadEmployeeData() async {
    var box = await Hive.openBox<Employee>(boxName);
    box.put(0, Employee(10001, 'Lara', 'Manager', 30000));
    box.put(1, Employee(10002, 'Kathryn', 'Manager', 30000));
    box.put(2, Employee(10003, 'Lara', 'Developer', 15000));
    box.put(3, Employee(10004, 'Michael', 'Designer', 15000));
    box.put(4, Employee(10005, 'Martin', 'Developer', 15000));
    box.put(5, Employee(10006, 'Newberry', 'Developer', 15000));
    box.put(6, Employee(10007, 'Balnc', 'Developer', 15000));
    box.put(7, Employee(10008, 'Perry', 'Developer', 15000));
    box.put(8, Employee(10009, 'Gable', 'Developer', 15000));
    box.put(9, Employee(10010, 'Grimes', 'Developer', 15000));
  }
 
  void addEmployee(Employee newEmployee) async {
    var box = await Hive.openBox<Employee>(boxName);
    await box.add(newEmployee);
    employeeList = box.values.toList();
    refresh();
  }
 
  void getEmployees() async {
    var box = await Hive.openBox<Employee>(boxName);
    employeeList = box.values.toList();
    refresh();
  }
 
  List<Employee> getEmployeesList() {
    getEmployees();
    return employeeList;
  }
 
 
  void updateEmployee({Employee employee, int key}) async {
    var box = await Hive.openBox<Employee>(boxName);
    await box.putAt(key, employee);
    employeeList = box.values.toList();
    refresh();
  }
 
  void deleteEmployee(key) async {
    var box = await Hive.openBox<Employee>(boxName);
    await box.deleteAt(key);
    employeeList = box.values.toList();
    refresh();
  }
}

 

STEP 5: Create class for TypeAdaptor. Here we have created a custom TypeAdaptor for the Employee class.

import 'package:hive/hive.dart';
import 'employee.dart';
 
class EmployeeAdaptor extends TypeAdapter<Employee> {
  @override
  final int typeId = 0;
 
  @override
  Employee read(BinaryReader reader) {
    final numOfFields = reader.readByte();
    final fields = <int, dynamic>{
      for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
    };
    return Employee(
      fields[0] as int,
      fields[1] as String,
      fields[2] as String,
      fields[3] as int,
    );
  }
 
  @override
  void write(BinaryWriter writer, Employee obj) {
    writer
      ..writeByte(4)
      ..writeByte(0)
      ..write(obj.id)
      ..writeByte(1)
      ..write(obj.name)
      ..writeByte(2)
      ..write(obj.designation)
      ..writeByte(3)
      ..write(obj.salary);
  }
 
  @override
  int get hashCode => typeId.hashCode;
 
  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is EmployeeAdaptor &&
          runtimeType == other.runtimeType &&
          typeId == other.typeId;
}

 

STEP 6: Register the type adapter in the main function, and add the hive initialization.

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Hive.initFlutter();
  Hive.registerAdapter(EmployeeAdaptor());
  runApp(MyApp());
}
 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: EmployeeListScreen(),
    );
  }
}

 

STEP 7: Create an EmployeeDataGridSource class which extends with the DataGridSource, to create the collection of the DataGridRow for the SfDataGrid.

class EmployeeDataSource extends DataGridSource {
  EmployeeDataSource({this.employeeDatabase}) {
    initialLoading();
    employeeDatabase.addListener(handleListUpdates);
  }
 
  EmployeeDatabase employeeDatabase;
 
  List<Employee> employeeData = [];
 
  List<DataGridRow> _employeeDataGridRow = [];
 
  void initialLoading() {
    employeeData = employeeDatabase.getEmployeesList();
    buildDataGridRows();
  }
 
  void handleListUpdates() {
    employeeData = employeeDatabase.employeeList;
    buildDataGridRows();
    notifyListeners();
  }
 
  void buildDataGridRows() {
    _employeeDataGridRow = employeeData
        .map<DataGridRow>(
          (employee) => DataGridRow(
            cells: [
              DataGridCell<int>(columnName: 'id', value: employee.id),
              DataGridCell<String>(columnName: 'name', value: employee.name),
              DataGridCell<String>(
                  columnName: 'designation', value: employee.designation),
              DataGridCell<int>(columnName: 'salary', value: employee.salary),
            ],
          ),
        )
        .toList();
  }
 
  void updateDataGridSource() {
    notifyListeners();
  }
 
  @override
  List<DataGridRow> get rows => _employeeDataGridRow;
 
  @override
  DataGridRowAdapter buildRow(DataGridRow row) {
    return DataGridRowAdapter(
        cells: row.getCells().map<Widget>((e) {
      return Container(
        alignment: Alignment.center,
        padding: EdgeInsets.all(8.0),
        child: Text(e.value.toString()),
      );
    }).toList());
  }
}

 

STEP 8: Wrap the SfDataGrid inside the GetBuilder widget. Initialize the SfDataGrid with all the required details. Here we have provided the option to perform the crud operation with the hive database.

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('DataGrid Sample'),
        backgroundColor: Colors.blue,
        actions: [
          MaterialButton(
            onPressed: () {
              showAddEmployee(context);
            },
            child: Icon(Icons.add),
          ),
          MaterialButton(
            onPressed: () {
              showDeleteEmployee(context);
            },
            child: Icon(Icons.delete),
          ),
        ],
      ),
      body: GetBuilder<EmployeeDatabase>(
        builder: (database) {
          return SfDataGrid(
              source: dataGridSource,
              onCellTap: (DataGridCellTapDetails tapDetails) {
                if (tapDetails.rowColumnIndex.rowIndex == 0) {
                  return;
                }
                showUpdateEmployees(
                    context, tapDetails.rowColumnIndex.rowIndex);
              },
              columnWidthMode: ColumnWidthMode.fill,
              columns: getColumns());
        },
      ),
    );
  }
}

 

View example in GitHub.

 

Did you find this information helpful?
Yes
No
Help us improve this page
Please provide feedback or comments
Comments (0)
Please  to leave a comment
Access denied
Access denied