flutter api fetch json loop null safety


誰のための文章ですか。


json解析は他の言語ではよくできていますが、flufではよくできていない人だけが
flutter fetch network cookbookを見ましたが、うまくいかなかったら

full code:

import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;



Future<List> fetchAlbum() async {
  final list = <Map>[];
  final response = await http
      .get(Uri.parse('<API_URL>'));

  if (response.statusCode == 200) {
    // If the server did return a 200 OK response,
    // then parse the JSON.

    var responseBody = jsonDecode(response.body);
    responseBody.forEach( (element) {
      list.add(element);
    });




    return list;

  } else {
    // If the server did not return a 200 OK response,
    // then throw an exception.
    throw Exception('Failed to load album');
  }
}


class Method {
  final int id;
  final int name;
  final String description;
  final DateTime created_at;
  final DateTime updated_at;
  final DateTime deleted_at;

  const Method(
      {
        required this.id,
        required this.name,
        required this.description,
        required this.created_at,
        required this.updated_at,
        required this.deleted_at}
      );

  factory Method.fromJson(Map<String, dynamic> json) {
    return Method(
      id: json['id'],
      name: json['name'],
      description: json['description'],
      created_at: json['created_at'],
      updated_at: json['updated_at'],
      deleted_at: json['deleted_at'],
    );
  }
}



void main() => runApp(const MyApp());

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  // late Future<Method> futureAlbum;
  late Future<List> futureAlbum;

  @override
  void initState() {
    super.initState();
    futureAlbum = fetchAlbum();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Fetch Data Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Fetch Data Example'),
        ),
        body: Center(
          child: FutureBuilder<List>(
            future: futureAlbum,
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                // print(snapshot.data?[0]['id']);
                final returnThis = snapshot.data?[0]['name'].toString() ?? 'No data';
                return Text(returnThis);


              } else if (snapshot.hasError) {
                return Text('${snapshot.error}');
              }

              // By default, show a loading spinner.
              return const CircularProgressIndicator();
            },
          ),
        ),
      ),
    );
  }
}

ヒント:

.runtimeTypeによってデータ型が決定される.
許容nullタイプと非許容nullタイプは、?および??によってよく区別される.

説明:


以下のjsonデータがあるとします.
[
    {
        "id": 1,
        "name": "삼성 카드",
        "description": "카드 결제",
        "created_at": "2022-03-27T13:33:13.000000Z",
        "updated_at": "2022-03-27T13:33:40.000000Z",
        "deleted_at": null
    },
    {
        "id": 2,
        "name": "국민 카드",
        "description": "카드 결제",
        "created_at": "2022-03-27T13:33:50.000000Z",
        "updated_at": "2022-03-27T13:33:50.000000Z",
        "deleted_at": null
    },
    {
        "id": 3,
        "name": "현대 카드",
        "description": "카드 결제",
        "created_at": "2022-03-27T13:34:03.000000Z",
        "updated_at": "2022-03-27T13:34:03.000000Z",
        "deleted_at": null
    },
]
fl振動の立場から見ると、[]があるのでリスト形式です.
中には<key>:<value>がディックシェリー形態で、地図で識別できます.final list = <Map>[];が用意されています
次に、ROUを回転させて準備したリストに入れます.
var responseBody = jsonDecode(response.body);
    responseBody.forEach( (element) {
      list.add(element);
    });
このようにリストに入れてある今アプリ画面で皆さんに見せたいと思います
 child: FutureBuilder<List>(
            future: futureAlbum,
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                // print(snapshot.data?[0]['id']);
                final returnThis = snapshot.data?[0]['name'].toString() ?? 'No data';
                return Text(returnThis);


              } else if (snapshot.hasError) {
                return Text('${snapshot.error}');
              }

              // By default, show a loading spinner.
              return const CircularProgressIndicator();
            },
          ),
一般print(snapshot.data?[0]['id']);はコンソールウィンドウによく印刷され、Text() WidgetはStringしか受信できません.nullのStringですか?納得できない.
だから一度.final returnThis = snapshot.data?[0]['name'].toString() ?? 'No data';文がnullでない場合はsnapshot.data?[0]['name'].toString()、nullである場合は'No data'です.
仕上げたら、下のビューだけが正常です.

ps.
振動が困難を感じるのは,主に2つの原因による.
1つ目はnullセキュリティの!, ?, ??, ??=, ...etcなどnullに関連する多くのオペレータです.Dartチームはこれを予想しているかもしれませんが、公式サイトはcheatsheetを提供しています.
2つ目は静的タイプと呼ばれますが、タイプ化言語に非常に近いです.
特にtyped languageのため、多くのGenericsは何とかtypeを維持しようとします.
genericsは一度理解すればflutの方が気持ちがいいので、ぜひ時間を割いて理解することをお勧めします