Summary - Note app
- Flutter course
- Intermediate
- Lesson 85/99
- 4 min
Combine all parts and finish a working note app.
A working note app
A working note app combines four parts: the Note model carries data, ListView lists notes, Navigator.push and Navigator.pop manage the add/edit flow, and shared_preferences makes notes persistent. Each part has its own responsibility and together they form a coherent flow.
final notlar = <Note>[];
// add button
onPressed: () async {
final yeni = await Navigator.push(context,
MaterialPageRoute(builder: (_) => EklemeEkrani()));
if (yeni != null) {
notlar.add(yeni);
await notlariKaydet(notlar);
}
},Practice Write the add flow
Define a StatefulWidget named NotlarEkrani. In its State have a final notlar = <Note>[] list. The build method should return a Scaffold whose body is a ListView.builder (itemCount: notlar.length and each row returning ListTile(title: Text(n.baslik))). The floatingActionButton should be a FloatingActionButton whose onPressed calls Navigator.push with MaterialPageRoute(builder: (_) => EklemeEkrani()). Print 'hazir' in main.
Starter code
import 'package:flutter/material.dart';
class Note {
final String id;
final String baslik;
final String icerik;
Note(this.id, this.baslik, this.icerik);
}
class EklemeEkrani extends StatelessWidget {
const EklemeEkrani({super.key});
@override
Widget build(BuildContext context) => const SizedBox.shrink();
}
// NotlarEkrani StatefulWidget tanımla
// State içinde final notlar = <Note>[] olsun
// build Scaffold döndürsün
// gövde ListView.builder olsun (itemCount ve ListTile)
// floatingActionButton Navigator.push ile MaterialPageRoute çağırsın
void main() {
// 'hazir' yazdır
}Sample solution
import 'package:flutter/material.dart';
class Note {
final String id;
final String baslik;
final String icerik;
Note(this.id, this.baslik, this.icerik);
}
class EklemeEkrani extends StatelessWidget {
const EklemeEkrani({super.key});
@override
Widget build(BuildContext context) => const SizedBox.shrink();
}
class NotlarEkrani extends StatefulWidget {
const NotlarEkrani({super.key});
@override
State<NotlarEkrani> createState() => _NotlarEkraniState();
}
class _NotlarEkraniState extends State<NotlarEkrani> {
final notlar = <Note>[];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Notlar')),
body: ListView.builder(
itemCount: notlar.length,
itemBuilder: (context, index) {
final n = notlar[index];
return ListTile(title: Text(n.baslik));
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => const EklemeEkrani()),
);
},
child: const Icon(Icons.add),
),
);
}
}
void main() {
print('hazir');
}Expected output
hazir
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 In what order does data flow in the note app?
- shared_preferences → Navigator → ListView → Note
- Navigator → Note → shared_preferences → ListView
- ListView → shared_preferences → Note → Navigator
- Note → ListView → Navigator → shared_preferences Correct answer
Explanation: First the Note model carries the data, ListView displays it, Navigator handles add/edit, and finally shared_preferences makes it persistent. The other orders are illogical.
2 Await a value with Navigator
final yeni = await Navigator.push(
context,
____(builder: (_) => EklemeEkrani()),
);
final yeni = await Navigator.push(
context,
MaterialPageRoute(builder: (_) => EklemeEkrani()),
);
Explanation: Navigator.push takes a MaterialPageRoute; this is the classic Navigator 1.0 approach. GoRoute belongs to GoRouter, and Scaffold and Container are widgets; none are route definitions.
3 Summary parts
| Term | Meaning |
|---|---|
Note |
Data model |
ListView |
Note list |
Navigator |
Screen transitions |
shared_preferences |
Persistent storage |