#android #flutter #dart #mobile-development
#Android #флаттер #dart #мобильная разработка
Вопрос:
Я смог прочитать несколько руководств по Flutter о базовом дизайне пользовательского интерфейса и новичок в вызовах API. Я думаю, что мне нужно преобразовать типы после выполнения вызова API, но я понятия не имею, как.
Примечание: Я знаю, что в одном файле слишком много кода, но я отделю файл вызова API и файл пользовательского класса от моего основного файла
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<Country> fetchAlbum() async {
final response = await http.get('https://restcountries.eu/rest/v2/all');
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Country.fromJson(json.decode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
class Country {
final String name;
final List<String> topLevelDomain;
final String alpha2Code;
final String alpha3Code;
final String callingCodes;
final String capital;
final String region;
final String subregion;
final int population;
final List<int> latlng;
final String demonym;
final int area;
final int gini;
final List<String> timezones;
final List<String> borders;
final String nativeName;
final int numericCode;
final List<String> currencies;
final List<String> translations;
final String flag;
final String cioc;
Country({
@required this.name,
@required this.topLevelDomain,
@required this.alpha2Code,
@required this.alpha3Code,
@required this.callingCodes,
@required this.capital,
@required this.region,
@required this.subregion,
@required this.population,
@required this.latlng,
@required this.demonym,
@required this.area,
@required this.gini,
@required this.timezones,
@required this.borders,
@required this.nativeName,
@required this.numericCode,
@required this.currencies,
@required this.translations,
@required this.flag,
@required this.cioc,
});
factory Country.fromJson(Map<String, dynamic> json) {
return Country(
name: json['name'],
topLevelDomain: json['topLevelDomain'],
alpha2Code: json['alpha2Code'],
alpha3Code: json['alpha3Code'],
callingCodes: json['callingCodes'],
capital: json['capital'],
region: json['region'],
subregion: json['subregion'],
population: json['population'],
latlng: json['latlng'],
demonym: json['demonym'],
area: json['area'],
gini: json['gini'],
timezones: json['timezones'],
borders: json['borders'],
nativeName: json['nativeName'],
numericCode: json['numericCode'],
currencies: json['currencies'],
translations: json['translations'],
flag: json['flag'],
cioc: json['cioc'],
);
}
}
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
MyApp({Key key}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Future<Country> 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: Text('Fetch Data Example'),
),
body: Center(
child: FutureBuilder<Country>(
future: futureAlbum,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data.name);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner.
return CircularProgressIndicator();
},
),
),
),
);
}
}
Вот как выглядит экран моего эмулятора:http://i1.imgrr.com/18Z/7512_Screenshot1599026660.png
Комментарии:
1. Попробуйте использовать
factory Country.fromJson(Map<dynamic, dynamic> json)
2. список типов<динамический> не является общим типом карты<динамический, dynamic>
3. Попробуйте использовать factory Country.FromJSON(динамический json)
Ответ №1:
строка 12 ‘возвращает Country.FromJSON(json.decode(response.body));’
Я думаю, что тип ‘json.decode (response.body)’ — это ‘Список’, но тип параметра здесь — Map . Возможно, ваш ответ представляет собой список объектов Country, но он возвращает 1 объект Country. Вот почему вы получили эту ошибку
Комментарии:
1. Вероятно, это все; что мне сделать, чтобы изменить возвращаемый тип?
2. это зависит от вас. этот API возвращает список. таким образом, вы можете сначала получить список, запустить цикл и преобразовать каждый элемент (тип — Map) в свой объект и делать то, что вы хотите
3. Я новичок в Flutter; не могли бы вы, пожалуйста, выписать код и объяснить его мне?
4.
Future<List> fetchAlbum() async { final response = await http.get('https://restcountries.eu/rest/v2/all'); if (response.statusCode == 200) { // If the server did return a 200 OK response, // then parse the JSON. List list = []; json.decode(response.body).forEach((e) => list.add(Country.fromJson(e)) ); return list; } else { // If the server did not return a 200 OK response, // then throw an exception. throw Exception('Failed to load album'); } }
5. вам нужно изменить функцию return Future<Список>, если вы хотите использовать список стран. или верните только 1 страну, которую вы хотите использовать
Ответ №2:
Ваш API возвращает List
вместо Map
.
Вам нужно сопоставить каждый элемент как Country
.
Future<List<Country>> fetchAlbum() async {
final response = await http.get('https://restcountries.eu/rest/v2/all');
if (response.statusCode == 200) {
List<Country> countryList = ((json.decode(response.body) as List).map((i) => Country.fromJson(i)).toList();
return countryList;
} else {
throw Exception('Failed to load album');
}
}
Комментарии:
1. На экране моего эмулятора написано «тип List<dynamic> не является подтипом List<String>». Вот код: pastebin.pl/view/9e948ee9
2. Пожалуйста, обратитесь к этой ссылке, чтобы правильно сгенерировать свой заводской код. Вставьте свой ответ json здесь, и он сгенерирует класс для вас javiercbk.github.io/json_to_dart