Flutter跨页面传值并保存到ListView问题求助
Hey there, let's break down and fix your issues one by one. I've gone through your code and spotted several key problems causing the unexpected behavior:
1. Why clicking save does nothing & content is empty in console
The core issue here is that your data.content only gets updated when you trigger onFieldSubmitted (like pressing Enter in the TextField). When you directly tap the save icon, this callback never runs—so data.content stays empty, failing your if (data.content != '') check, hence no action happens.
Fix:
Update your AddingTextField to sync content to Data in real-time as the user types, and ensure the save button navigates back to the home page after saving:
class _AddingTextFieldState extends State<AddingTextField> { TextEditingController _textEditingController; @override void initState() { _textEditingController = TextEditingController(text: widget.text); // Sync initial edit content to Data if provided if (widget.text != null) { context.read<Data>().addContent(widget.text); } super.initState(); } @override Widget build(BuildContext context) { var data = context.read<Data>(); return Padding( padding: const EdgeInsets.all(15), child: TextFormField( controller: _textEditingController, maxLines: widget.maxLines, decoration: InputDecoration(hintText: widget.hintText), // Update Data.content whenever text changes onChanged: (value) { data.addContent(value); }, ), ); } }
Then fix the save button action in AddNoteScreen:
CustomAppBar( title: 'Add Note', icon: Icons.save, onPressed: () { print(data.content); if (data.content.isNotEmpty) { data.addNote(); Navigator.pop(context); // Critical: return home to refresh ListView } }, ),
2. Data not showing up in home ListView
Your Data class has inconsistencies in data handling and persistence:
- You commented out all title logic but still include
titlesin file operations, leading to corrupted data - String-splitting for file I/O is error-prone (breaks if notes contain
|/,/[]) - Redundant code like
content=content;inaddNote
Fix the Data class (overhauled for reliability):
class Data extends ChangeNotifier { String content = ''; int? editingIndex; // Track if we're editing an existing note List<Map<String, String>> notes = []; // Better structure: list of note objects void addContent(String value) { content = value; print('Updated content: $content'); notifyListeners(); } /// Add new note or update existing one void saveNote() { if (content.isEmpty) return; final now = DateTime.now(); final currentTime = '${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}'; if (editingIndex != null) { // Update existing note notes[editingIndex!] = {'content': content, 'time': currentTime}; editingIndex = null; } else { // Add new note notes.add({'content': content, 'time': currentTime}); } content = ''; notifyListeners(); writeFile(); } void removeNote(int index) { notes.removeAt(index); notifyListeners(); writeFile(); } // Prepare for editing a note void editNote(int index) { content = notes[index]['content']!; editingIndex = index; notifyListeners(); } Future<String> appPath() async { final document = await getApplicationDocumentsDirectory(); return document.path; } Future<File> appFile() async { final path = await appPath(); return File('$path/notes.json'); } // Use JSON for reliable serialization Future writeFile() async { final file = await appFile(); return file.writeAsString(jsonEncode(notes)); } Future readFile() async { try { final file = await appFile(); if (!await file.exists()) { notes = []; return; } final jsonString = await file.readAsString(); final List<dynamic> decoded = jsonDecode(jsonString); notes = decoded.map((item) => Map<String, String>.from(item)).toList(); notifyListeners(); } catch (e) { print('Error loading notes: $e'); notes = []; } } }
Update AddNoteScreen to support edit mode:
class AddNoteScreen extends StatelessWidget { final String? editContent; final int? editIndex; AddNoteScreen({this.editContent, this.editIndex}); @override Widget build(BuildContext context) { var data = context.watch<Data>(); // Initialize edit state if needed if (editIndex != null && editContent != null) { WidgetsBinding.instance.addPostFrameCallback((_) { data.editNote(editIndex!); }); } return Scaffold( body: SafeArea( child: Column( children: <Widget>[ CustomAppBar( title: editIndex != null ? 'Edit Note' : 'Add Note', icon: Icons.save, onPressed: () { if (data.content.isNotEmpty) { data.saveNote(); Navigator.pop(context); } }, ), Flexible( child: AddingTextField( maxLines: 500, text: editContent ?? '', hintText: 'Write your note...', ), ), ], ), ), ); } }
3. Clicking ListTile doesn't open edit page
In your home page's ListView.builder, pass the note's content and index to AddNoteScreen when tapping a ListTile:
ListView.builder( itemCount: data.notes.length, itemBuilder: (context, index) { final note = data.notes[index]; return ListTile( title: Text(note['content']!.substring(0, 20) + '...'), subtitle: Text(note['time']!), onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => AddNoteScreen( editContent: note['content'], editIndex: index, ), ), ); }, trailing: IconButton( icon: Icon(Icons.delete), onPressed: () => data.removeNote(index), ), ); }, )
Final Quick Checks
- Ensure you've wrapped your app with
ChangeNotifierProviderforDatainmain.dart - Call
data.readFile()when your app starts (e.g., inmain.dartafter initializing the provider) to load saved notes
内容的提问来源于stack exchange,提问作者AzReddy

