Eine Liste aus JSON
Teil des Abschnitts Daten und Netzwerk der Flutter-Journey von Coddy. Lektion 18 von 27.
Viele Antworten sind Listen: jedes Buch, jede Nachricht, jeder Tag einer Vorhersage. In JSON wird eine Liste in eckigen Klammern geschrieben, und hier ist jedes Element ein Objekt:
[
{"title": "Frankenstein", "author": "Mary Shelley"},
{"title": "Pride and Prejudice", "author": "Jane Austen"}
]jsonDecode wandelt eckige Klammern in eine List um. Auch ihre Elemente sind dynamic, also gib mit as an, was du erwartest: List<dynamic> für die Liste, Map<String, dynamic> für jedes Element.
Wandle dann jedes Element mit map in ein Book um und sammle die Ergebnisse mit toList():
final items = jsonDecode(body) as List<dynamic>;
return items
.map((item) => Book.fromJson(item as Map<String, dynamic>))
.toList();map allein ergibt ein verzögert ausgewertetes Iterable, keine List, deshalb steht dort toList(). Der Bildschirm verfügt dann über eine List<Book> für ListView.builder.
Aufgabe
MittelDas Regal zeigt nur das erste Buch. Sorge dafür, dass loadBooks jedes Element der Liste mit items.map(...) und .toList() in ein Book umwandelt.
Probier es selbst
import 'dart:convert';
import 'package:flutter/material.dart';
import 'api.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: BooksScreen(),
);
}
}
class BooksScreen extends StatefulWidget {
const BooksScreen({super.key});
@override
State<BooksScreen> createState() => _BooksScreenState();
}
class _BooksScreenState extends State<BooksScreen> {
late Future<List<Book>> _books;
@override
void initState() {
super.initState();
_books = loadBooks();
}
Future<List<Book>> loadBooks() async {
final body = await fetch('/books');
final items = jsonDecode(body) as List<dynamic>;
return [Book.fromJson(items[0] as Map<String, dynamic>)];
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Books')),
body: FutureBuilder<List<Book>>(
future: _books,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(child: Text('Could not load: ${snapshot.error}'));
}
if (snapshot.hasData) {
final books = snapshot.data!;
return ListView.builder(
itemCount: books.length,
itemBuilder: (context, index) {
final book = books[index];
return ListTile(
title: Text(book.title),
subtitle: Text(book.author),
);
},
);
}
return const Center(child: CircularProgressIndicator());
},
),
);
}
}
class Book {
Book({required this.title, required this.author});
final String title;
final String author;
factory Book.fromJson(Map<String, dynamic> json) {
return Book(
title: json['title'] as String,
author: json['author'] as String,
);
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Daten und Netzwerk
2Ladebildschirme
Ein Spinner während des LadensFutureBuilder kennenlernenEinmalig in initState ladenDaten per Button neu ladenZum Aktualisieren nach unten ziehen5Datumsangaben und Preise
Datumsangaben mit DateFormatUhrzeiten mit DateFormatPreise mit NumberFormatÜbe selbstständig: Online-Flutter-Compiler