Flutter代码报Expected an identifier错误,请求排查修复
Flutter Todo应用错误修复:Expected an identifier.dart(missing_identifier)
错误定位
报错的核心原因是TodoListScreen的build方法中,ListView.builder的itemBuilder参数未正确实现。原代码仅写了itemBuilder: (),不符合Dart语法要求——itemBuilder必须接收带BuildContext和索引int的回调函数,且需返回对应的列表项组件。同时原代码缺失了触发添加功能的输入框与按钮,导致添加逻辑无法被调用。
解决方案
替换错误的itemBuilder部分,补充完整的回调逻辑;同时添加底部输入栏与添加按钮,完善交互功能。此外还增加了空值判断与错误提示,提升代码鲁棒性和用户体验。
完整修复后的代码
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; void main() => runApp(TodoApp()); class TodoApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Todo App', theme: ThemeData( primarySwatch: Colors.blue, ), home: TodoListScreen(), ); } } class Todo { final int id; final String title; bool isDone; Todo({ required this.id, required this.title, this.isDone = false, }); factory Todo.fromJson(Map<String, dynamic> json) { return Todo( id: json['id'], title: json['title'], isDone: json['isDone'] ?? false, // 增加空值判断,避免API返回null导致错误 ); } } class TodoListScreen extends StatefulWidget { @override _TodoListScreenState createState() => _TodoListScreenState(); } class _TodoListScreenState extends State<TodoListScreen> { final TextEditingController _todoTitleController = TextEditingController(); final List<Todo> _todos = []; @override void initState() { super.initState(); _fetchTodos(); } void _fetchTodos() async { final response = await http.get(Uri.parse('https://todoapp-api.apps.k8s.gu.se/todos')); if (response.statusCode == 200) { final jsonList = jsonDecode(response.body) as List<dynamic>; final todos = jsonList.map((json) => Todo.fromJson(json)).toList(); setState(() { _todos.clear(); _todos.addAll(todos); }); } else { // 错误提示 ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('加载待办列表失败')), ); } } void _addTodo() async { final newTodoTitle = _todoTitleController.text.trim(); if (newTodoTitle.isNotEmpty) { final response = await http.post( Uri.parse('https://todoapp-api.apps.k8s.gu.se/todos'), headers: {'Content-Type': 'application/json'}, body: jsonEncode({'title': newTodoTitle, 'isDone': false}), ); if (response.statusCode == 201) { final newTodo = Todo.fromJson(jsonDecode(response.body)); setState(() { _todos.add(newTodo); }); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('添加待办项失败')), ); } _todoTitleController.clear(); } } void _toggleTodoStatus(Todo todo) async { final response = await http.patch( Uri.parse('https://todoapp-api.apps.k8s.gu.se/todos/${todo.id}'), headers: {'Content-Type': 'application/json'}, body: jsonEncode({'isDone': !todo.isDone}), ); if (response.statusCode == 200) { setState(() { todo.isDone = !todo.isDone; }); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('更新待办状态失败')), ); } } void _deleteTodo(Todo todo) async { final response = await http.delete(Uri.parse('https://todoapp-api.apps.k8s.gu.se/todos/${todo.id}')); if (response.statusCode == 204) { setState(() { _todos.remove(todo); }); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('删除待办项失败')), ); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Todo List'), ), body: Column( children: [ Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ Expanded( child: TextField( controller: _todoTitleController, decoration: InputDecoration( hintText: '输入新的待办项', border: OutlineInputBorder(), ), ), ), SizedBox(width: 8), ElevatedButton( onPressed: _addTodo, child: Text('添加'), ), ], ), ), Expanded( child: ListView.builder( itemCount: _todos.length, itemBuilder: (context, index) { final todo = _todos[index]; return ListTile( title: Text( todo.title, style: TextStyle( decoration: todo.isDone ? TextDecoration.lineThrough : null, ), ), leading: Checkbox( value: todo.isDone, onChanged: (_) => _toggleTodoStatus(todo), ), trailing: IconButton( icon: Icon(Icons.delete, color: Colors.red), onPressed: () => _deleteTodo(todo), ), ); }, ), ), ], ), ); } }
额外优化说明
- 在
Todo.fromJson中增加json['isDone'] ?? false,避免API返回null时触发类型错误 - 给所有网络请求添加了错误提示SnackBar,提升用户体验
- 补充了输入栏和添加按钮,实现完整的待办项添加流程
内容的提问来源于stack exchange,提问作者eddin99
相关产品推荐
相关产品推荐

