Eksik JSON Alanları
Coddy'nin Flutter Journey'sinin Veri ve Ağ bölümünün bir parçası. Ders 19 / 27.
Gerçek verilerde eksikler olur. /books içinde iki kitabın "subtitle" değeri vardır, Pride and Prejudice kitabında ise yoktur. Olmayan bir anahtar için json['subtitle'], null değerini verir ve null as String hata verir: tüm liste type 'Null' is not a subtype of type 'String' hatasıyla yüklenemez.
Sonuna ? eklenen bir tür null da tutabilir. String?, "bir metin dizisi ya da hiçbir şey" demektir:
final String? subtitle;
subtitle: json['subtitle'] as String?,Dart, bu nedenle onu kullandığın her yerde eksik değerle ilgilenmeni gerektirir. ??, null için yedek bir değer sağlar:
Text(book.subtitle ?? 'No subtitle')book.subtitle! da yazabilirsin; bu, Dart'a "bana güven, değer null değil" demektir. Sunucudan gelen veriler söz konusu olduğunda bu, tutamayacağın bir sözdür: alt başlığı olmayan kitapta ! ekranın çökmesine neden olur. ! işaretini, hasData sonrasında snapshot.data! gibi kontrol ettiğin yerlerde kullan.
Görev
OrtaBir kitabın alt başlığı olmadığı için raf yüklenemiyor. Alt başlığı isteğe bağlı yap:
- alan bir
String?olsun,as String?olarak oku - liste, alt başlığı olmayan bir kitap için
No subtitlegösterir
Kendin dene
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 items.map((item) => Book.fromJson(item as Map<String, dynamic>)).toList();
}
@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.subtitle),
);
},
);
}
return const Center(child: CircularProgressIndicator());
},
),
);
}
}
class Book {
Book({required this.title, required this.subtitle});
final String title;
final String subtitle;
factory Book.fromJson(Map<String, dynamic> json) {
return Book(
title: json['title'] as String,
subtitle: json['subtitle'] as String,
);
}
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Veri ve Ağ bölümündeki tüm dersler
3Çağrılar Başarısız Olduğunda
try ile Hataları YakalamaHata Fırlatmafinally ile TemizlemeFutureBuilder Hata DurumuYeniden Dene DüğmesiKendi başına pratik yap: Online Flutter derleyicisi