Нулевая безопасность для списка? Ненулевая карта Json из запроса GET http

#flutter #dart

Вопрос:

Я учусь выполнять http — запросы в Dart / Flutter.

Я попытался выполнить запрос GET из простого api по адресу https://jsonplaceholder.typicode.com/posts

У меня есть необработанный json, но его нужно разобрать и сопоставить.

Моя проблема в том, что документация, которой я следовал, кажется устаревшей, а синтаксис, который я использовал со СПИСКОМ, больше не соответствует нулевой безопасности.

  1. Есть ли лучший способ выполнять http-запросы в Dart / Flutter?
  2. Есть ли лучший способ инициализировать мой
 List<DataModel> model;
 

это позволяет обеспечить соответствие нулевой безопасности без учета большого количества кода?

главная.дротик

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

домашний экран.дротик

 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;
  }
}
 

Комментарии:

1. В чем проблема? Неужели код at getData не работает? Вы получаете сообщение об ошибке?

2. Я получал ненулевую ошибку безопасности flutter null, List<DataModel> model; которую мне нужно было добавить late final , чтобы устранить ошибку.

Ответ №1:

Вы должны иметь возможность использовать ключевое late слово и сделать его final переменной, так initState() как оно всегда вызывается и поэтому model не может быть пустым.

Вы можете узнать больше о последних конечных переменных здесь

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

Примечание: Предлагая вам использовать final , я предполагаю, что вы model больше никуда не переназначаетесь.

Комментарии:

1. Это было решением проблемы. Ранее сегодня я пытался сделать это поздно, но я не знал, что это нужно окончательно.

2. @StephenStilwell В целом, вы должны предпочесть сделать переменную обнуляемой , а late не, особенно если переменная будет инициализирована асинхронно. Вы не можете определить, была ли late переменная инициализирована или нет.

3. @jamesdlin DataModel будет просто получать json от вызываемого api, обычно запрос GET или POST

4. @StephenStilwell Тот факт, что модель будет инициализирована из асинхронного запроса для получения HTTP-запроса, является еще одной причиной, по которой она должна быть обнулена, а late не . Что мешает build вызвать ваш метод до завершения HTTP-запроса?