我正在尝试使用flatter_riverpod的stateNotificationProvider检索和删除TodoList。在下面的代码中,fetchTodoList方法工作正常,但deleteTodoList法不工作。
UI
class TodoList extends ConsumerWidget {
@override
Widget build(BuildContext context, ScopedReader watch) {
final todoAsyncValue = watch(todoFutureProvider);
return Padding(
padding: const EdgeInsets.all(8),
child: todoAsyncValue.when(
data: (todoList) => SingleChildScrollView(
child: Scaffold(
body: Column(
children: _buildTodoList(todoList),
),
floatingActionButton: FloatingActionButton(
onPressed: context.read(todoNotifierProvider.notifier).deleteTodoList(),
child: const Icon(Icons.delete),
),
),
),
loading: () => const Center(child: const CircularProgressIndicator()),
error: (error, stack) => Text(error.toString()),
),
);
}
_buildTodoList(){ // ......}
}
提供商&类
final todoNotifierProvider = StateNotifierProvider<TodoListStateNotifier, List<Todo>>((ref) {
return TodoListStateNotifier();
});
final todoFutureProvider = FutureProvider<List<Todo>>((ref) async {
final todo= ref.read(todoNotifierProvider.notifier);
await todo.fetchTodoList();
return ref.watch(todoNotifierProvider);
});
class TodoListStateNotifier extends StateNotifier<List<Todo>>{
TodoListStateNotifier(): super([]);
Future<void> fetchTodoList() async {
final todoClient = TodoClient();
state = await todoClient.fetchTodoList();
}
void deleteTodoList() {
var list = <Todo>[];
list = state.removeLast();
state = list;
}
}
将显示以下错误消息。
类型为"Todo"的值不能分配给类型为的变量"列表"。
此外,如果我将代码转换为以下内容,则不会显示错误,但它不会正确反映在UI中。
void deleteTodoList() {
state.removeLast();
}
我假设下面代码中定义的类型就是状态的类型,我错了吗?
class TodoListStateNotifier extends StateNotifier<List<Todo>>{
是否无法读取代码中的状态?
如果你知道更好的方法,请告诉我。
这里removeLast()
方法返回一个Todo
,正好是列表中最后一个Todo
,这就是错误的原因
不能将'Todo'类型的值分配给'List'类型的变量
因为您确实试图将Todo分配给List。
void deleteTodoList() {
var list = <Todo>[];
list = state.removeLast();
state = list;
}
现在使用第二个示例,您可以有效地删除最后一个项,但不会发出新的状态,因此UI不会重新生成。
void deleteTodoList() {
state.removeLast();
}
备选方案:
- 筛选并删除所需的特定todo
state = state.where((todo) => todo.id != target.id).toList()
- 不要将删除的值分配给变量
void deleteTodoList() {
var list = <Todo>[];
state.removeLast();
list=state;
state = list;
}
- 使用省道级联运算符和展开运算符
使用排列运算符(…(复制列表,并使用级联运算符为应用的方法不返回删除的项。
void deleteTodoList() {
state=[...state..removeLast()];
}
每次重建UI时,都会调用该函数。错误在这里:
onPressed: context.read(todoNotifierProvider.notifier).deleteTodoList(),
你可以删除()
,也可以写:
onPressed: () => context.read(todoNotifierProvider.notifier).deleteTodoList(),