-
什么是Hive?
Hive 是一个 No-SQL 轻量级和快速键值数据库解决方案,它是跨平台的(在移动设备、桌面和 Web 上运行)并且是用纯 Dart 编写的。与不支持 Flutter web 的 sqflite 相比,这使其具有立竿见影的优势——Hive 具有任何原生依赖项,因此它可以在 web 上无缝运行。
-
深入了解何时以及为什么应该使用 hive。
据统计,在写入或删除方面,Hive 大大优于 SQLite 和 SharedPreferences,在从存储中读取数据方面,SharedPreferences 在读取性能方面与 Hive 不相上下。SQLite 的表现要差得多。下图显示了基准测试是在搭载 Android Q 的 Oneplus 6T 上执行的。
上图说明了为什么应该使用 hive,这带来了一个挥之不去的问题“我什么时候应该使用 hive?”。
“无论你是谁或做什么,迟早你都需要将数据存储在你的应用程序中,然后再检索它。”
当您需要一个简单的数据库在您的设备上存储数据并且不希望从服务器同步时,您可以使用 hive。
-
在 Flutter 项目中设置 Hive 数据存储
设置 hive 以在您的 Flutter 项目中使用非常简单,只需几个步骤如下所示。
将数据库的 hive 包、TypeAdapters 的 hive_generator、path_provider 包(为设备上的 DB 设置位置)添加到 Flutter 项目中的 pub spec.yaml 文件
创建一个异步函数来设置您的数据库并在此示例中调用运行应用程序的主函数中的函数,我的函数名称是“setUpLocator”。
在 hive 中存储数据时,您将 hive 数据存储中的每个数据部分视为一个盒子,在下图中您可以观察到您需要打开盒子,不要忘记您创建或打开的每个盒子都必须有它的自己的唯一密钥。
为了使您的代码更具可读性和可维护性,建议创建一个类来保存数据库的密钥,如下图所示
通过这几个步骤,您已经 “成功”地在您的颤振项目中设置了 hive,接下来是利用 hive 数据存储来存储您需要在应用程序中存储的任何数据。
-
在 Flutter 应用程序中执行基本操作,例如从 Hive 数据存储中创建、更新和删除数据
创建数据
您可以使用这几行代码将数据添加到配置单元数据存储中。在下图中,我以用户输入的形式添加了一个字符串列表(标题和描述),这在您更新数据时几乎相同。在幕后,您正在覆盖附加到该蜂巢盒的数据。
获取数据
您可以通过将您的唯一密钥传递给该配置单元框来从配置单元数据存储中获取数据。
盒子的唯一钥匙
删除/删除数据
您可以使用配置单元框的唯一键从配置单元数据存储中删除数据
提供者的方式🥰。
- 设置你的 hive 包依赖并添加提供程序包(指定的版本可以更新)。
- 根据您的用例生成并注册您的适配器,并使用构建运行程序包生成文件。
- 创建 Hive 服务可侦听提供程序并将其添加到多提供程序中的提供程序列表中。
- 创建您的 BaseViewModel(这是可选的,您的 Hive 服务可以扩展 ChangeNotifier)。
- 创建您的 Hive 服务类。
- 将您的 Hive 服务类连接到您的 UI,该 UI 将用作侦听您的 UI 的控制器。
- 我们将创建一个带有 Hive 服务类的迷你常规检查器应用程序,用于显示和执行基本任务功能。
设置你的hive包依赖并添加provider包(指定的版本可以更新)
您只需要添加项目所需的依赖项,如下所示;
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
# get_it for dependency injection
get_it: ^7.2.0
# provider to handle state
provider: ^6.0.1
# the official hive package
hive: ^2.0.5
# a dependency to the hive package
hive_flutter: ^1.1.0
# hepls format our date and time
intl: ^0.17.0
dev_dependencies:
flutter_lints: ^2.0.1
flutter_test:
sdk: flutter
hive_generator: ^1.1.1
build_runner: ^2.1.7
- 根据您的用例生成和注册您的适配器,并使用构建运行程序包生成文件
输入数据库字段并生成适配器
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
part 'routinedb.g.dart';
@HiveType(typeId: 0)
class RoutineDb extends HiveObject {
@HiveField(0)
String title;
@HiveField(1)
String description;
@HiveField(2)
bool missed;
@HiveField(3)
bool done;
@HiveField(4)
TimeOfDay routineTime;
@HiveField(5)
DateTime routimeDate;
RoutineDb({
required this.title,
required this.description,
required this.missed,
required this.done,
required this.routimeDate,
required this.routineTime,
});
}
使用 build_runner 包生成适配器
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'routinedb.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class RoutineDbAdapter extends TypeAdapter<RoutineDb> {
@override
final int typeId = 0;
@override
RoutineDb read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return RoutineDb(
title: fields[0] as String,
description: fields[1] as String,
missed: fields[2] as bool,
done: fields[3] as bool,
routimeDate: fields[5] as DateTime,
routineTime: fields[4] as TimeOfDay,
);
}
@override
void write(BinaryWriter writer, RoutineDb obj) {
writer
..writeByte(6)
..writeByte(0)
..write(obj.title)
..writeByte(1)
..write(obj.description)
..writeByte(2)
..write(obj.missed)
..writeByte(3)
..write(obj.done)
..writeByte(4)
..write(obj.routineTime)
..writeByte(5)
..write(obj.routimeDate);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is RoutineDbAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
class TimeOfDayAdapter extends TypeAdapter<TimeOfDay> {
@override
final typeId = 101;
@override
void write(BinaryWriter writer, TimeOfDay obj) {
writer
..writeByte(2)
..writeByte(0)
..write(obj.hour)
..writeByte(1)
..write(obj.minute);
}
@override
TimeOfDay read(BinaryReader reader) {
var numOfFields = reader.readByte();
var fields = <int, dynamic>{
for (var i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return TimeOfDay(hour: fields[0] as int, minute: fields[1] as int);
}
}
- 注册您的适配器
创建并将您的 Hive 服务、可侦听的提供者添加到多提供者中的 SingleChildWidget 提供者列表
在本节中,我们将 hive 服务作为 Listenable provider() 添加到提供程序包提供的多提供程序类的提供程序列表中。
创建您的 BaseViewModel(这是可选的,您的 Hive 服务可以扩展 ChangeNotifier)
在本节中,我们创建一个扩展 changeNotifier 的抽象类,该类将包含辅助函数,例如(initState 和 dispose,它们基于计划的显示帧),我们可以在整个应用程序中使用它们来进行状态管理
import 'dart:async';
import 'dart:developer';
import 'package:estate_project/src/utils/enums.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
abstract class BaseViewModel extends ChangeNotifier {
bool _isLoading = false;
bool _isDisposed = false;
bool _isInitializeDone = false;
ViewState _state = ViewState.idle;
bool get isLoading => _isLoading;
bool get isDisposed => _isDisposed;
ViewState get state => _state;
bool get isInitialized => _isInitializeDone;
FutureOr<void> _initState;
BaseViewModel() {
SchedulerBinding.instance.addPostFrameCallback((_) {
//after displaying the frames on schedule we want to run our init function
//this makes us avoid using stateful widget while using this architecture
_init();
log("init called VM...");
});
}
FutureOr<void> initState();
FutureOr<void> disposeState();
//this serves as an init state
void _init() async {
_initState = initState();
await _initState;
_isInitializeDone = true;
initState();
}
//changes the state of the bool based on the supplied parameter
changeLoaderStatus(bool status) {
_isLoading = status;
notifyListeners();
}
//we can keep track of the state of the ui with this function
changeEnumState(ViewState viewState) {
_state = viewState;
notifyListeners();
}
@override
void dispose() {
_isDisposed = true;
disposeState();
super.dispose();
}
}
创建您的 Hive 服务类
在我们将扩展抽象类 BaseViewModel 的 Hive 服务具体类中,我们将创建基本函数来处理基于逻辑的任务的迷你常规检查器应用程序的基本任务,例如(获取所有任务,将项目添加到任务,创建例行公事...等)。Hive 服务类将更像一个监听我们的用户界面的控制器。
class HiveService extends BaseViewModel {
@override
FutureOr<void> initState() async {
log("instantiating --->>> hive service");
String hi = getFirstCharactersOfRoutine("Table Cut");
logConsole(hi);
}
@override
FutureOr<void> disposeState() async {
//close the hive box after the hive box have been dispose
await Hive.close();
}
//database logic
List<RoutineDb> routineDbList = [];
UnmodifiableListView<RoutineDb> get routineDbListGetter =>
UnmodifiableListView(routineDbList);
// Create new routine of the routineDb model
Future<void> createARoutine(RoutineDb routineDb) async {
Box<RoutineDb> box = await Hive.openBox<RoutineDb>(routineDbBoxKeys);
await box.add(routineDb);
routineDbList.add(routineDb);
routineDbList = box.values.toList();
notifyListeners();
}
// Get a list of routineDb model in the database
Future<List<RoutineDb>> getRoutineItems() async {
Box<RoutineDb> box = await Hive.openBox<RoutineDb>(routineDbBoxKeys);
routineDbList = box.values.toList();
return routineDbList;
}
// remove a routinebd model based on the key in the database
Future<void> addItem(RoutineDb routineDb) async {
Box<RoutineDb> box = await Hive.openBox<RoutineDb>(routineDbBoxKeys);
await box.delete(routineDb.key);
routineDbList = box.values.toList();
notifyListeners();
}
}
将您的 Hive 服务类连接到您的 UI,该 UI 将用作侦听您的 UI 的控制器
下面的代码片段展示了我们如何将 HiveService 连接到我们的 UI 的示例。在这种情况下,OverviewProvider 扩展了 Hive 服务,在我们的 hive 服务中,有一个 getRoutine 函数来获取所有例程
class OverViewScreen extends StatelessWidget {
const OverViewScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BaseView<OverViewProvider>(
vmBuilder: (context) => OverViewProvider(context: context),
builder: _buildScreen,
);
}
Widget _buildScreen(BuildContext context, OverViewProvider overviewModel) {
return FutureBuilder<List<RoutineDb>>(
future: overviewModel.getRoutineItems(),
builder: (context, snapshot) {
if (snapshot.hasData) {
if (overviewModel.routineDbList.isEmpty) {
return const NoRoutinePlaceHolder();
}
return Container(
margin: EdgeInsets.symmetric(horizontal: 10.w, vertical: 20.h),
child: SingleChildScrollView(
child: Column(
children: [
for (int i = 0; i < overviewModel.routineDbList.length; i++)
RoutineTile(
routinIsEditable: true,
editFunction: () {
AppNavigator.pushNamed(
editScreen,
arguments: overviewModel.routineDbList[i],
);
},
tileSubTitle:
DateTimeFormatter.formatDateTimeToNormalString(
overviewModel.routineDbList[i].routimeDate),
titleString: snapshot.data![i].title,
),
],
),
),
);
//if the routine db list is empty
} else {
return const Loader();
}
});
}
}
我们将创建一个带有 Hive 服务类的迷你常规检查器应用程序,用于显示和执行基本任务功能
在这种情况下,我将展示向例程添加项目、创建例程、获取例程等功能
- 添加项目
// remove a routinebd model based on the key in the database
Future<void> addItem(RoutineDb routineDb) async {
Box<RoutineDb> box = await Hive.openBox<RoutineDb>(routineDbBoxKeys);
await box.delete(routineDb.key);
routineDbList = box.values.toList();
notifyListeners();
}
- 创建例程
// Create new routine of the routineDb model
Future<void> createARoutine(RoutineDb routineDb) async {
log("ref creating a routine of title =>>> ${routineDb.title}");
Box<RoutineDb> box = await Hive.openBox<RoutineDb>(routineDbBoxKeys);
await box.add(routineDb);
routineDbList.add(routineDb);
routineDbList = box.values.toList();
notifyListeners();
}
- 例行公事
// Get a list of routineDb model in the database
Future<List<RoutineDb>> getRoutineItems() async {
Box<RoutineDb> box = await Hive.openBox<RoutineDb>(routineDbBoxKeys);
routineDbList = box.values.toList();
return routineDbList;
}
我希望你能够看到如何在你的flutter项目中使用 hive 和 provider 的概述。
在这里分享以下这份最新版《flutter进阶学习笔记》资料内容全面、结构清晰,希望能帮助到大家学习flutter并提升自己的实力,如有需要参考的可以看下面 ↓↓↓
有需要的可以复制下方链接,传送直达!!!
https://docs.qq.com/doc/DQmhUZUhnWGhCVEZH