feat:增加hive模块
This commit is contained in:
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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
61
lib/models/todo.g.dart
Normal 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;
|
||||
}
|
||||
@@ -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(() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
24
lib/service/todo_service.dart
Normal file
24
lib/service/todo_service.dart
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()) &&
|
||||
|
||||
Reference in New Issue
Block a user