我有一个使用 Flutter + 提供程序构建的待办事项列表应用程序。它不是添加多个任务,而是在添加新任务时替换当前任务。另外,控制台中存在一些与 setState() 相关的错误。我的问题是如何添加多个任务?
这是完整的代码。谢谢您的帮助!
main.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:todoey_flutter/models/task_data.dart';
import 'screens/tasks_screen.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => TaskData(),
child: const MaterialApp(
home: TasksScreen(),
),
);
}
}
模型/task_data.dart
import 'package:flutter/foundation.dart';
import 'package:todoey_flutter/models/task.dart';
import 'dart:collection';
class TaskData extends ChangeNotifier {
final List<Task> _tasks = [];
UnmodifiableListView<Task> get tasks {
return UnmodifiableListView(_tasks);
}
int get taskCount {
return _tasks.length;
}
void addTask(String newTaskTitle) async {
final task = Task(name: newTaskTitle);
_tasks.add(task);
notifyListeners();
}
void updateTask(Task task) async {
task.toggleDone();
notifyListeners();
}
void deleteTask(Task task) async {
_tasks.remove(task);
notifyListeners();
}
}
models/task.dart
class Task {
final String name;
bool isDone;
Task({required this.name, this.isDone = false});
void toggleDone() {
isDone = !isDone;
}
}
屏幕/add_task_screen.dart
import 'package:flutter/material.dart';
import 'package:todoey_flutter/models/task_data.dart';
import 'package:provider/provider.dart';
class AddTaskScreen extends StatelessWidget {
const AddTaskScreen({super.key});
@override
Widget build(BuildContext context) {
String newTaskTitle = '';
return Container(
color: const Color(0xff757575),
child: Container(
padding: const EdgeInsets.all(20.0),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
const Text('Add Task',
textAlign: TextAlign.center,
style:
TextStyle(fontSize: 30.0, color: Colors.lightBlueAccent)),
TextField(
autofocus: true,
textAlign: TextAlign.center,
onChanged: (newText) {
newTaskTitle = newText;
},
),
TextButton(
child: const Text(
'Add New Task',
style: TextStyle(
fontSize: 30.0,
color: Colors.lightBlue,
),
),
onPressed: () {
final taskData = Provider.of<TaskData>(context, listen: false);
taskData.addTask(newTaskTitle);
Navigator.pop(context);
},
),
],
),
),
);
}
}
屏幕/tasks_screen.dart
import 'package:flutter/material.dart';
import 'package:todoey_flutter/models/task_data.dart';
import 'package:todoey_flutter/widgets/tasks_list.dart';
import 'package:todoey_flutter/screens/add_task_screen.dart';
import 'package:provider/provider.dart';
class TasksScreen extends StatelessWidget {
const TasksScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.lightBlueAccent,
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.lightBlueAccent,
child: const Icon(Icons.add),
onPressed: () {
showModalBottomSheet(
context: context,
builder: (BuildContext context) => const AddTaskScreen());
},
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: const EdgeInsets.only(
top: 60.0, left: 30.0, right: 30.0, bottom: 30.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const CircleAvatar(
backgroundColor: Colors.white,
radius: 30.0,
child: Icon(
Icons.list,
size: 30.0,
color: Colors.lightBlueAccent,
),
),
const SizedBox(
height: 10.0,
),
const Text(
'Todoey',
style: TextStyle(
color: Colors.white,
fontSize: 50.0,
fontWeight: FontWeight.w700,
),
),
Text(
'${Provider.of<TaskData>(context).taskCount} Tasks',
style: const TextStyle(
color: Colors.white,
fontSize: 18.0,
),
),
],
),
),
Expanded(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
),
),
child: const TasksList(),
),
),
],
),
);
}
}
小部件/tasks_list.dart
import 'package:flutter/material.dart';
import 'package:todoey_flutter/widgets/tasks_tile.dart';
import 'package:provider/provider.dart';
import 'package:todoey_flutter/models/task_data.dart';
class TasksList extends StatelessWidget {
const TasksList({super.key});
@override
Widget build(BuildContext context) {
return Consumer<TaskData>(
builder: (context, taskData, child) {
return ListView.builder(
itemBuilder: (context, index) {
final task = taskData.tasks[index];
return TaskTile(
isChecked: task.isDone,
taskTitle: task.name,
checkboxCallback: (checkboxState) {
taskData.updateTask(task);
},
longPressCallback: () {
taskData.deleteTask(task);
},
);
},
itemCount: taskData.taskCount,
);
},
);
}
}
小部件/tasks_tile.dart
import 'package:flutter/material.dart';
class TaskTile extends StatelessWidget {
final bool isChecked;
final String taskTitle;
final Function(bool?) checkboxCallback;
final Function longPressCallback;
const TaskTile(
{super.key,
required this.isChecked,
required this.taskTitle,
required this.checkboxCallback,
required this.longPressCallback});
@override
Widget build(BuildContext context) {
return ListTile(
onLongPress: longPressCallback(),
title: Text(
taskTitle,
style: TextStyle(
decoration:
isChecked ? TextDecoration.lineThrough : TextDecoration.none),
),
trailing: Checkbox(
activeColor: Colors.lightBlueAccent,
value: isChecked,
onChanged: checkboxCallback,
),
);
}
}
我收到这些控制台警告和错误。
TaskData 发送通知为: “任务数据”的实例 ════════════════════════════════════════ ══════════ ════════════════════════════════════════ ══════════
(2) 抛出另一个异常:在构建期间调用了 setState() 或 markNeedsBuild()。
有人可以帮我解决这个问题吗?我还分享我的 pubspec.yaml 文件以供参考。我正在使用 Flutter 3.13.8(最新)
name: todoey_flutter
description: A Todo List Application Using Flutter
publish_to: "none"
version: 1.0.0+1
environment:
sdk: ">=3.0.0 <4.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
provider: ^6.0.2
flutter_launcher_icons: "^0.13.1"
flutter_launcher_icons:
android: "launcher_icon"
ios: true
image_path: "assets/icon/icon.png"
min_sdk_android: 21
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.0
flutter:
uses-material-design: true
在
AddTaskScreen
中,您像这样调用了通知程序的 addTask
方法:
final taskData = Provider.of<TaskData>(context, listen: false);
taskData.addTask(newTaskTitle);
你应该这样称呼它:
context.read<TaskData>().addTask(newTaskTitle);