小说网站怎么做流量吗,如何发布一个网页,dedecms做电影网站,高端建设网站公司Flutter 数据持久化存储之Hive 前言正文一、配置项目二、UI① 增加UI② 显示和删除UI 三、使用Hive① 初始化Hive② TypeAdapter自定义对象③ 注册TypeAdapter③ CURD 四、源码 前言 在Flutter中#xff0c;有多种方式可以进行数据持久化存储。以下是一些常见的方式#xff1… Flutter 数据持久化存储之Hive 前言正文一、配置项目二、UI① 增加UI② 显示和删除UI 三、使用Hive① 初始化Hive② TypeAdapter自定义对象③ 注册TypeAdapter③ CURD 四、源码 前言 在Flutter中有多种方式可以进行数据持久化存储。以下是一些常见的方式 Shared Preferences 使用shared_preferences插件可以将数据存储在设备的轻量级持久化存储中。这种方式适合存储少量简单的键值对数据比如用户偏好设置等。 文件存储 使用dart:io库可以进行文件存储可以将数据以文件的形式存储在设备上。这种方式适合存储结构化数据可以使用JSON格式或者其他格式进行数据的读写。 SQLite数据库 可以使用sqflite插件在Flutter应用中使用SQLite数据库。SQLite是一种轻量级的关系型数据库适合于需要存储结构化数据并进行高效查询的场景。 NoSQL数据库 一些Flutter插件如moor也提供了对NoSQL数据库的支持比如使用对象数据库如Hive来存储数据。 云存储 通过与云存储如Firebase Firestore、AWS Amplify等进行集成可以将数据存储在云端实现跨设备数据同步和备份。
以上的这些我们都不使用这里要使用的是Hive库地址是 Hive感兴趣的可以自行了解本文运行效果图。 正文 Hive是一个轻量级、快速的本地数据库解决方案适用于在移动应用程序中进行数据持久化存储。Hive采用高效的自定义序列化算法能够在移动设备上快速读写数据适用于处理结构化数据。并且Hive是用纯Dart编写的这使得它比不支持Flutter网络的SQLite更有优势。
一、配置项目 首先我们创建一个名为study_hive的项目。 创建项目之后我们配置一下依赖库在项目的pubspec.yaml文件中添加如下所示代码
dependencies:get:hive:hive_flutter:dev_dependencies:hive_generator:build_runner:在dependencies中我添加了get和hive的库在dev_dependencies中添加了一个构建对象的依赖库。冒号后面没有写版本号就是获取该库最新的版本。添加位置如下图所示 然后点击Pub get获取对应的依赖库即可到这里为止我们的配置工作就完成了。
二、UI 在使用Hive库时我们需要想一下用这个库去做什么先设想一个应用场景而不是写到哪里就是哪里乱枪打鸟不可取。我们就写这样一个场景对于人员信息的操作可以增加、查询、修改、删除、删除所有。基于这个场景我们就可以去设计UI了我们尽量在一个页面去解决更直观一些PS我也是偷一个懒。 首先我们在lib目录下新建一个page包page包下新建一个hive_page.dart里面的代码如下
import package:flutter/material.dart;class HivePage extends StatelessWidget {overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text(Hive Demo),),body: Container(color: Colors.blue,),);}
}当前页面很简单就是一个标题和蓝色背景当然你现在还看不到的我们需要修改一下main.dart中的代码
import package:flutter/material.dart;
import package:study_hive/page/hive_page.dart;void main() async {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});overrideWidget build(BuildContext context) {return MaterialApp(title: Hive Demo,theme: ThemeData(primaryColor: Colors.blueAccent,appBarTheme: const AppBarTheme(elevation: 0),),home: HivePage(),);}
} 这里的修改就是去掉了原来默认代码并且加载我们刚写好的HivePage下面我们可以运行一下虚拟器或者真机都可以。 ① 增加UI
在HivePage的build()中增加如下代码 ///通用输入框Widget baseEdit(String hintText, TextInputType type,TextEditingController textController) {return Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(10),border: Border.all(color: Colors.black87,width: 1.0,),),margin: const EdgeInsets.only(top: 6),padding: const EdgeInsets.all(0),height: 44,child: TextField(textInputAction: TextInputAction.none,keyboardType: type,cursorColor: Colors.black87,cursorWidth: 1,controller: textController,decoration: InputDecoration(contentPadding: const EdgeInsets.only(left: 10),filled: true,fillColor: Colors.white,hintText: hintText,hintStyle: const TextStyle(textBaseline: TextBaseline.alphabetic,color: Colors.grey,),border: OutlineInputBorder(borderRadius: BorderRadius.circular(10),borderSide: BorderSide.none,),),),);}这里的代码就是构建一个输入框的组件将里面的提示文本、键盘类型和输入框控制器抽离了出来。控制器我们就放到GetX中使用在page包下新建一个hive_controller.dart代码如下所示
import package:flutter/material.dart;
import package:get/get.dart;class HiveController extends GetxController {late TextEditingController nameEditController,ageEditController;overridevoid onInit() {super.onInit();nameEditController TextEditingController();ageEditController TextEditingController();}
}这里主要就是对于输入框控制器的初始化。回到HivePage的build中再写两个组件代码如下 var size4 const SizedBox(height: 4,width: 4,);///保存按钮var saveBtn TextButton(onPressed: () {print(Save);},child: const Text(Save,style: TextStyle(color: Colors.blue),)); 一个是间隔一个是保存按钮然后我们可以再写一个组件用来包含刚才所写的内容。这里面就需要用到baseEdit去构建两个输入框因此我们加上GetX在page包下新建一个hive_controller.dart代码如下所示
import package:flutter/material.dart;
import package:get/get.dart;class HiveController extends GetxController {late TextEditingController nameEditController,ageEditController;overridevoid onInit() {super.onInit();nameEditController TextEditingController();ageEditController TextEditingController();}
}回到HivePage中在build中增加一个组件代码如下 ///保存组件var saveWidget Container(width: MediaQuery.of(context).size.width,margin: const EdgeInsets.all(8),padding: const EdgeInsets.all(8),decoration: BoxDecoration(color: Colors.white,borderRadius: BorderRadius.circular(12.0),),child: Column(mainAxisSize: MainAxisSize.min,children: [baseEdit(Name, TextInputType.name, controller.nameEditController),size4,baseEdit(Age, TextInputType.number, controller.ageEditController),saveBtn],),);最后我们再修改一下返回的Scaffold中的代码在这里我们加载刚才写好的保存组件如下所示 return Scaffold(appBar: AppBar(title: const Text(Hive Demo),),body: Container(color: Colors.blue,child: Column(children: [saveWidget],),),);这里你需要注意的就是代码的顺序了当前这个组件在最下边通过一张图来说明。 运行一下 这样增加的UI就写好了下面我们构建显示和删除的。
② 显示和删除UI
在build中添加如下代码 ///列表组件var listWidget Expanded(child: Container(width: MediaQuery.of(context).size.width,// 允许高度自适应margin: const EdgeInsets.only(left: 8, right: 8, bottom: 8),padding: const EdgeInsets.all(8),decoration: BoxDecoration(color: Colors.white,borderRadius: BorderRadius.circular(12.0),),));var deleteAllBtn ElevatedButton(onPressed: () {print(DeleteAll);},child: const Row(mainAxisSize: MainAxisSize.min,children: [Icon(Icons.delete, color: Colors.red),SizedBox(width: 4),Text(DeleteAll,style: TextStyle(color: Colors.red),)],));再修改一下返回的Scaffold将列表和按钮组件添加进去代码如下所示 return Scaffold(appBar: AppBar(title: const Text(Hive Demo),),body: Container(color: Colors.blue,child: Column(children: [saveWidget, listWidget, deleteAllBtn],),),);再保存一下热重载效果如图所示 三、使用Hive
下面我们就可以开始使用Hive了之前我们已经添加过依赖了下面我们首先进行初始化。
① 初始化Hive 在Flutter中使用Hive我们需要在main()函数中进行初始化注意导包语句
import package:hive_flutter/hive_flutter.dart;main()函数代码如下所示
void main() async {//初始化Hiveawait Hive.initFlutter();runApp(const MyApp());
}初始化之后我们就可以去使用了在此之前我们需要明确使用的方式因为我们操作的是对象包含常规的数据类型因此我们就需要自定义对象。
② TypeAdapter自定义对象 在lib下创建一个models目录该目录下创建person.dart文件代码如下
class Person {String name;int age;Person({required this.name,required this.age});
}这是标准的对象代码然后我们可以使用Hive注释这个类和类里面的变量然后快速生成一个TypeAdapter类代码下面我们修改一下Person的代码如下
import package:hive/hive.dart;part person.g.dart;HiveType(typeId: 1)
class Person {HiveField(0)String name;HiveField(1)int age;Person({required this.name, required this.age});
}首先注意导包的语句这里的part person.g.dart;语句会标红这是因为目前还没有这个文件这个文件就是我们需要快捷生成的。HiveType 和 HiveField 是 Hive 数据库中用来定义对象映射和序列化的注解。 HiveType: HiveType 是一个标记注解用于标识 Hive 中的自定义对象类。它告诉 Hive 数据库被注解的类是一个 Hive 对象需要进行序列化和反序列化。当你在定义自己的模型类时可以使用 HiveType() 注解来标记这个类以便 Hive 可以识别并处理这个类。所有的 typeId 允许在 0 到 223 之间不可以重复。 HiveField: HiveField 是用来标记类中的字段成员变量的注解用于指定字段在 Hive 数据库中的位置和顺序。当你在定义自己的模型类时可以使用 HiveField() 注解来标记类中的字段以便 Hive 可以按照指定的顺序进行序列化和反序列化。字段编号的范围可为 0~255不可以重复。 下面我们通过在Terminal中输入一行代码生成对应的TypeAdapter对象类代码如下所示
flutter packages pub run build_runner build输入后回车如下图所示 你会看到对应的person.g.dart文件就已经生成在models文件夹中里面的代码如下所示
// GENERATED CODE - DO NOT MODIFY BY HANDpart of person.dart;// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************class PersonAdapter extends TypeAdapterPerson {overridefinal int typeId 1;overridePerson read(BinaryReader reader) {final numOfFields reader.readByte();final fields int, dynamic{for (int i 0; i numOfFields; i) reader.readByte(): reader.read(),};return Person(name: fields[0] as String,age: fields[1] as int,);}overridevoid write(BinaryWriter writer, Person obj) {writer..writeByte(2)..writeByte(0)..write(obj.name)..writeByte(1)..write(obj.age);}overrideint get hashCode typeId.hashCode;overridebool operator (Object other) identical(this, other) ||other is PersonAdapter runtimeType other.runtimeType typeId other.typeId;
}下面我们注册TypeAdapter对象
③ 注册TypeAdapter 依然是修改main()函数注意一点在打开使用Hive的盒子之前需要先注册TypeAdapter代码如下所示
import package:flutter/material.dart;
import package:hive_flutter/hive_flutter.dart;
import package:study_hive/models/person.dart;
import package:study_hive/page/hive_page.dart;void main() async {//初始化Hiveawait Hive.initFlutter();//注册TypeAdapterHive.registerAdapter(PersonAdapter());//打开盒子await Hive.openBoxPerson(personBox);runApp(const MyApp());
}注意导包语句现在我们的盒子就打开了盒子名称是personBox这个可以自己去定义的下面我们就可以正式去使用这个盒子来进行CURD了。
③ CURD 在进行CURD时我们将代码写在GetxController中提供相关的函数进行操作下面我们修改一下HiveController中的代码
import package:flutter/material.dart;
import package:get/get.dart;
import package:hive_flutter/hive_flutter.dart;
import package:study_hive/models/person.dart;class HiveController extends GetxController {late TextEditingController nameEditController, ageEditController;final personBox Hive.boxPerson(personBox);overridevoid onInit() {super.onInit();nameEditController TextEditingController();ageEditController TextEditingController();}void save() {var person Person(name: nameEditController.text, age: int.parse(ageEditController.text));personBox.add(person);nameEditController.clear();ageEditController.clear();}void modify(int index, Person person) {personBox.putAt(index, person);}void delete(int index) {personBox.deleteAt(index);}void deleteAll() {personBox.clear();}overridevoid onClose() {nameEditController.dispose();ageEditController.dispose();super.onClose();}
}上面的代码解释一下首先我们获取personBox盒子对象final personBox Hive.boxPerson(personBox);然后就是save()函数中获取输入框的值进行保存保存之后再清空输入框这里就没有对输入框的内容判空处理需要注意一下。modify()函数中通过下标和person对象就可以完成删除和删除所有就是可以直接处理的就没有什么好说的。你会发现没有查询这是因为Hive提供了一个名为ValueListenableBuilder 的小部件它只在数据库内的任何数值被修改时才会刷新。下面我们就可以在HivePage中去使用刚才所写的函数。
首先我们修改一下listWidget组件的代码 var listWidget Expanded(child: Container(width: MediaQuery.of(context).size.width,margin: const EdgeInsets.only(left: 8, right: 8, bottom: 8),padding: const EdgeInsets.all(8),decoration: BoxDecoration(color: Colors.white,borderRadius: BorderRadius.circular(12.0),),child: ValueListenableBuilder(valueListenable: controller.personBox.listenable(),builder: (context, box, widget) {if (box.isEmpty) {return const Center(child: Text(Empty),);} else {return ListView.builder(itemCount: box.length,itemBuilder: (context, index) {var personData box.getAt(index)!;return ListTile(title: Text(personData.name),subtitle: Text(personData.age.toString()),trailing: Row(mainAxisSize: MainAxisSize.min,children: Widget[IconButton(icon: const Icon(Icons.edit),onPressed: () {showModifyDialog(index, personData);},),IconButton(icon: const Icon(Icons.delete),onPressed: () {controller.delete(index);},),],),);});}})));这里的核心代码就是ValueListenableBuilder 的使用这里我们判断了box是否为空空就显示文字提示一下不为空就构建一个ListView显示Item数据。如下图所示 在列表的Item中我们除了显示用户的名称和年龄之外还有两个功能按钮分别用于修改和删除如下图所示 针对于删除很简单之后调用控制器里面写好的函数就可以了删除之后列表会自动刷新的。而修改的话屏幕上没有空间了因此我就写一个弹窗去显示需要修改的内容代码如下所示 void showModifyDialog(int index, Person personData) showDialog(context: context,builder: (BuildContext context) {TextEditingController nameController TextEditingController(text: personData.name);TextEditingController ageController TextEditingController(text: personData.age.toString());return AlertDialog(title: const Text(Modify Data),content: Column(mainAxisSize: MainAxisSize.min,children: [TextField(controller: nameController),TextField(controller: ageController)],),actions: [ElevatedButton(child: const Text(Modify),onPressed: () {var person Person(name: nameController.text,age: int.parse(ageController.text));controller.modify(index, person);Navigator.of(context).pop(); // 关闭对话框})],);});弹窗修改之后就关闭弹窗。最后我们再修改一下保存按钮和删除所有按钮组件的代码如下所示
var saveBtn TextButton(onPressed: () {controller.save();},child: const Text(Save,style: TextStyle(color: Colors.blue),));var deleteAllBtn ElevatedButton(onPressed: () {controller.deleteAll();},child: const Row(mainAxisSize: MainAxisSize.min,children: [Icon(Icons.delete, color: Colors.red),SizedBox(width: 4),Text(DeleteAll,style: TextStyle(color: Colors.red),)],));那么基本上代码就写完了下面我们整体看一下运行效果。 效果符合我的预期文章到这里就结束了元宵节快乐呀
四、源码
源码地址study_hive