#flutter #dart
Вопрос:
Я учусь выполнять http — запросы в Dart / Flutter.
Я попытался выполнить запрос GET из простого api по адресу https://jsonplaceholder.typicode.com/posts
У меня есть необработанный json, но его нужно разобрать и сопоставить.
Моя проблема в том, что документация, которой я следовал, кажется устаревшей, а синтаксис, который я использовал со СПИСКОМ, больше не соответствует нулевой безопасности.
- Есть ли лучший способ выполнять http-запросы в Dart / Flutter?
- Есть ли лучший способ инициализировать мой
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-запроса?