Home > OS >  Null-Safety for List? Non-nullable Json Map from GET http request
Null-Safety for List? Non-nullable Json Map from GET http request

Time:10-22

I am learning how to perform http requests in Dart / Flutter.

I tried to perform a GET request from a simple api at https://jsonplaceholder.typicode.com/posts

I got the raw json, but need to parse & map it out.

My problem is the documentation I was following seems outdated, and the syntax I used with LIST no longer follows null-safety.

  1. Is there a better way to perform http requests in Dart / Flutter?
  2. Is there a better way to initialize my
List<DataModel> model;

that allows for null-safety compliance without factoring a lot of code?

main.dart


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

import 'home_screen.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: HomeScreen(),
    );
  }
}

home_screen.dart

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

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

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

class _HomeScreenState extends State<HomeScreen> {
  List<DataModel> model;

  @override
  void initState() {
    getData();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
            title: Text('Http Get Request'),
        ),
        body: ListView.builder(itemBuilder: (BuildContext context, int index){
          return const Card(
            child: ExpansionTile(
                title: Text(model[index].title),
                children: [Text(model[index].body)],
            ),
          );
        },
          itemCount: model.length,
        ),
      );
  }

  Future<void> getData() async {
    Uri url = Uri.https('jsonplaceholder.typicode.com', '/posts');
    http.Response response = await http.get(url);
    print(response.body);
    List<dynamic> body = convert.jsonDecode(response.body);
    model = body.map((dynamic item) => DataModel.fromJson(item)).toList();
    setState(() {
    });
  }
}

data_model.dart

class DataModel {
  late int userId;
  late int id;
  late String title;
  late String body;

  DataModel({required this.userId, required this.id, required this.title, required this.body});

  DataModel.fromJson(Map<String, dynamic> json) {
    userId = json['userId'];
    id = json['id'];
    title = json['title'];
    body = json['body'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['userId'] = this.userId;
    data['id'] = this.id;
    data['title'] = this.title;
    data['body'] = this.body;
    return data;
  }
}

CodePudding user response:

You should be able to use the keyword late and make it a final variable since initState() is always called and so model cannot be null.

You can learn more about late final variables here

class _HomeScreenState extends State<HomeScreen> {
  late final List<DataModel> model;

Note: By suggesting you to use final, I'm assuming that you don't reassign model anywhere else.

  • Related