feat:增加hive模块

This commit is contained in:
2025-11-07 17:21:21 +08:00
parent 0f106f6adc
commit 00e65bc5be
12 changed files with 579 additions and 43 deletions

View File

@@ -1,12 +1,28 @@
import 'package:flisp_app/provider/app_provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:hive_flutter/adapters.dart';
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
import 'layout/main_screen.dart';
import 'models/todo.dart';
import 'provider/todo_provider.dart';
void main() {
void main() async{
WidgetsFlutterBinding.ensureInitialized();
// 初始化Hive
await Hive.initFlutter();
// 注册适配器
Hive.registerAdapter(TodoAdapter());
// 打开Box
await Hive.openBox<Todo>('todos');
final appDir = await getApplicationDocumentsDirectory();
print('📁 Hive数据库路径: ${appDir.path}');
runApp(const MyApp());
}

View File

@@ -1,48 +1,81 @@
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
class TodoItem {
num id;
String title;
String content;
bool isCompleted;
DateTime? dueDate;
TodoPriority priority;
part 'todo.g.dart';
TodoItem({
required this.id,
@HiveType(typeId: 0)
class Todo extends HiveObject {
@HiveField(0)
late int id;
@HiveField(1)
late String title;
@HiveField(2)
late String content;
@HiveField(3)
late bool isCompleted;
@HiveField(4)
late DateTime? dueDate;
@HiveField(5)
late int priorityIndex;
@HiveField(6)
late DateTime createTime;
@HiveField(7)
late DateTime updateTime;
TodoPriority get priority => TodoPriority.values[priorityIndex];
set priority(TodoPriority value) => priorityIndex = value.index;
Todo({
int? id,
required this.title,
required this.content,
this.content = '',
this.isCompleted = false,
this.dueDate,
this.priority = TodoPriority.medium,
});
TodoPriority priority = TodoPriority.medium,
DateTime? createTime,
DateTime? updateTime,
}) {
// 简单时间戳ID
this.id = id ?? DateTime.now().millisecondsSinceEpoch;
this.priorityIndex = priority.index;
this.createTime = createTime ?? DateTime.now();
this.updateTime = updateTime ?? DateTime.now();
}
TodoItem copyWith({
num? id,
Todo copyWith({
String? title,
String? content,
bool? isCompleted,
DateTime? dueDate,
TodoPriority? priority,
}) {
return TodoItem(
id: id ?? this.id,
return Todo(
id: id,
title: title ?? this.title,
content: content ?? this.content,
isCompleted: isCompleted ?? this.isCompleted,
dueDate: dueDate ?? this.dueDate,
priority: priority ?? this.priority,
createTime: createTime,
updateTime: DateTime.now(),
);
}
static TodoItem getEmpty() {
return TodoItem(
id: 0,
title: '',
content: '',
isCompleted: false,
dueDate: null,
priority: TodoPriority.medium,
static Todo getEmpty() {
return Todo(
id: 0,
title: '',
content: '',
isCompleted: false,
dueDate: null,
priority: TodoPriority.medium,
);
}
}

61
lib/models/todo.g.dart Normal file
View File

@@ -0,0 +1,61 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'todo.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class TodoAdapter extends TypeAdapter<Todo> {
@override
final int typeId = 0;
@override
Todo read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return Todo(
id: fields[0] as int?,
title: fields[1] as String,
content: fields[2] as String,
isCompleted: fields[3] as bool,
dueDate: fields[4] as DateTime?,
createTime: fields[6] as DateTime?,
updateTime: fields[7] as DateTime?,
)..priorityIndex = fields[5] as int;
}
@override
void write(BinaryWriter writer, Todo obj) {
writer
..writeByte(8)
..writeByte(0)
..write(obj.id)
..writeByte(1)
..write(obj.title)
..writeByte(2)
..write(obj.content)
..writeByte(3)
..write(obj.isCompleted)
..writeByte(4)
..write(obj.dueDate)
..writeByte(5)
..write(obj.priorityIndex)
..writeByte(6)
..write(obj.createTime)
..writeByte(7)
..write(obj.updateTime);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is TodoAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -1,4 +1,5 @@
import 'package:flisp_app/provider/todo_provider.dart';
import 'package:flisp_app/service/todo_service.dart';
import 'package:flisp_app/widgets/awesome_dialog.dart';
import 'package:flisp_app/widgets/todo_widget.dart';
import 'package:flutter/material.dart';
@@ -19,13 +20,15 @@ class TodoPage extends StatefulWidget {
}
class TodoPageState extends State<TodoPage> {
final TodoService todoService = TodoService();
// 待办事项列表
final List<TodoItem> _todos = [];
late List<Todo> _todos = [];
TodoTab _currentTab = TodoTab.all;
// 获取过滤后的待办事项
List<TodoItem> get _activeTodos {
List<Todo> get _activeTodos {
return getActiveTodos(_currentTab, _todos);
}
@@ -34,6 +37,38 @@ class TodoPageState extends State<TodoPage> {
_showTodoDialog(false, null);
}
@override
void initState() {
super.initState();
// _testAddTodo();
_testQueryTodos();
}
void _testQueryTodos() {
try {
_todos = todoService.getAllTodos();
} catch (e) {
print("失败");
print(e);
}
}
Future<void> _testAddTodo() async {
try {
// final newTodo = await todoService.addTodo(
// title: '测试待办事项',
// content: '这是一个测试内容',
// priority: TodoPriority.high,
// dueDate: DateTime.now().add(Duration(days: 3)),
// );
print("成功");
} catch (e) {
print("失败");
print(e);
}
}
@override
Widget build(BuildContext context) {
return buildBody(
@@ -86,7 +121,7 @@ class TodoPageState extends State<TodoPage> {
}
// 显示对话框
void _showTodoDialog(bool isEditing, TodoItem? todo) {
void _showTodoDialog(bool isEditing, Todo? todo) {
final todoProvider = Provider.of<TodoProvider>(context, listen: false);
if (isEditing) {
@@ -113,7 +148,7 @@ class TodoPageState extends State<TodoPage> {
}
// 保存待办事项
void _saveTodo(bool isEditing, TodoItem todo) {
void _saveTodo(bool isEditing, Todo todo) {
final store = Provider.of<TodoProvider>(context, listen: false);
setState(() {

View File

@@ -2,16 +2,16 @@ import 'package:flutter/material.dart';
import 'package:flisp_app/models/todo.dart';
class TodoProvider with ChangeNotifier {
TodoItem _formItem = TodoItem.getEmpty();
Todo _formItem = Todo.getEmpty();
TodoItem get formItem => _formItem;
Todo get formItem => _formItem;
void resetForm() {
_formItem = TodoItem.getEmpty();
_formItem = Todo.getEmpty();
notifyListeners();
}
void initForm(TodoItem todo) {
void initForm(Todo todo) {
_formItem.title = todo.title;
_formItem.content = todo.content ?? '';
_formItem.dueDate = todo.dueDate;

View File

@@ -0,0 +1,24 @@
import 'package:flisp_app/models/todo.dart';
import 'package:hive_flutter/hive_flutter.dart';
class TodoService {
static const String boxName = 'todos';
Box<Todo> get box => Hive.box<Todo>(boxName);
Future<void> addTodo(Todo todo) async {
await box.add(todo);
}
List<Todo> getAllTodos() {
return box.values.toList();
}
Future<void> updateTodo(Todo todo) async {
await todo.save();
}
Future<void> deleteTodo(Todo todo) async {
await todo.delete();
}
}

View File

@@ -1,6 +1,6 @@
import 'package:flisp_app/models/todo.dart';
List<TodoItem> getActiveTodos(TodoTab currentTab, List<TodoItem> todos) {
List<Todo> getActiveTodos(TodoTab currentTab, List<Todo> todos) {
switch (currentTab) {
case TodoTab.active:
return todos.where((todo) => !todo.isCompleted).toList();

View File

@@ -8,7 +8,7 @@ import 'package:flisp_app/utils/date_utils.dart';
class TodoForm extends StatefulWidget {
final GlobalKey<FormBuilderState> formKey;
final bool isEditing;
final TodoItem? initialTodo;
final Todo? initialTodo;
const TodoForm({
super.key,

View File

@@ -5,7 +5,7 @@ import 'package:flutter/material.dart';
import 'package:toggle_switch/toggle_switch.dart';
// 统计卡片
Widget buildStatsCard(List<TodoItem> todos) {
Widget buildStatsCard(List<Todo> todos) {
int totalCount = todos.length;
int activeCount = todos.where((todo) => !todo.isCompleted).length;
@@ -70,9 +70,9 @@ Widget buildTabs({
}
Widget buildTodoList({
required List<TodoItem> todos,
required List<Todo> todos,
required ValueChanged<String> onToggleTodo,
required ValueChanged<TodoItem> onEditTodo,
required ValueChanged<Todo> onEditTodo,
}) {
return ListView.separated(
itemCount: todos.length,
@@ -89,9 +89,9 @@ Widget buildTodoList({
}
Widget _buildTodoItem({
required TodoItem todo,
required Todo todo,
required ValueChanged<String> onToggle,
required ValueChanged<TodoItem> onEdit,
required ValueChanged<Todo> onEdit,
}) {
return buildCard(
child: ListTile(
@@ -113,7 +113,7 @@ Widget _buildTodoItem({
);
}
Widget _buildTodoTitle(TodoItem todo) {
Widget _buildTodoTitle(Todo todo) {
return Text(
todo.title,
style: TextStyle(
@@ -125,7 +125,7 @@ Widget _buildTodoTitle(TodoItem todo) {
}
// 构建待办事项副标题
Widget? _buildTodoSubtitle(TodoItem todo) {
Widget? _buildTodoSubtitle(Todo todo) {
final isOverdue =
todo.dueDate != null &&
todo.dueDate!.isBefore(DateTime.now()) &&