Menu
CoddyTech

Bir fromJson Kurucusu

Coddy'nin Flutter Journey'sinin Veri ve Ağ bölümünün bir parçası. Ders 17 / 27.

Ekranlarının her yerinde user['name'] as String okumak karmaşaya yol açar ve anahtardaki tek bir yazım hatası bunu bozar. Genellikle çözüm, veriler için JSON'u tanıyan tek bir yapıcıya sahip bir sınıf oluşturmaktır. Buna fromJson denir:

class User {
  User({required this.name, required this.age});

  final String name;
  final int age;

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      name: json['name'] as String,
      age: json['age'] as int,
    );
  }
}

User.fromJson, ikinci bir User oluşturma yolu olan adlandırılmış bir yapıcıdır. factory sözcüğü, bir yapıcının kod çalıştırmasına ve oluşturduğu nesneyi return etmesine olanak tanır. Sıradan bir yapıcı hiçbir şey return edemez.

Artık JSON tek bir yerde okunuyor. Uygulamanın geri kalanı, user.name değerinin bir String olduğu gerçek bir User elde ediyor; yazım hatası da null yerine derleme hatasına yol açıyor:

final body = await fetch('/user');
return User.fromJson(jsonDecode(body));

Sunucuyla iletişim kuran hemen hemen her uygulamada, aldığı her veri türü için bir fromJson bulunur.

challenge icon

Görev

Zor

Profilde Unknown yazıyor: loadUser, JSON'ı yok sayıyor. User sınıfına factory User.fromJson(Map<String, dynamic> json) ekleyerek name, email ve age değerlerini okumasını sağla ve loadUser işlevinin User.fromJson(jsonDecode(body)) döndürmesini sağla. dart:convert paketini içe aktar.

Kendin dene

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: ProfileScreen(),
    );
  }
}

class ProfileScreen extends StatefulWidget {
  const ProfileScreen({super.key});

  @override
  State<ProfileScreen> createState() => _ProfileScreenState();
}

class _ProfileScreenState extends State<ProfileScreen> {
  late Future<User> _user;

  @override
  void initState() {
    super.initState();
    _user = loadUser();
  }

  Future<User> loadUser() async {
    final body = await fetch('/user');
    print(body);
    return User(name: 'Unknown', email: 'unknown', age: 0);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Profile')),
      body: Center(
        child: FutureBuilder<User>(
          future: _user,
          builder: (context, snapshot) {
            if (snapshot.hasError) {
              return Text('Could not load: ${snapshot.error}');
            }
            if (snapshot.hasData) {
              final user = snapshot.data!;
              return Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Text(
                    user.name,
                    style: const TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
                  ),
                  const SizedBox(height: 8),
                  Text(user.email, style: const TextStyle(fontSize: 18)),
                  const SizedBox(height: 8),
                  Text('${user.age} years old'),
                ],
              );
            }
            return const CircularProgressIndicator();
          },
        ),
      ),
    );
  }
}

class User {
  User({required this.name, required this.email, required this.age});

  final String name;
  final String email;
  final int age;
}
quiz iconKendini test et

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

Kendi başına pratik yap: Online Flutter derleyicisi