Flutter (Dart) Цикл по результатам JSON - .length возвращает 0
Я новичок, чтобы трепетать и после некоторого хорошего прогресса застрял на том, что я, хотя и должен быть простой цикл. Я могу показать один результат от json, но не могу отобразить их все.
for(var i = 0; i < snapshot.data.posts.length; i++){
return Text(snapshot.data.posts[i].name + " - " + snapshot.data.posts[i].id + " - " + i.toString());
}
Поскольку этот код возвращается и выводит первый результат набора данных.
Mr. Nice - 1 - 0
Проблема в том, что я не могу заставить его выводить остальные результаты в наборе данных. Внешний JSON, который я анализирую, выглядит следующим образом (полностью)
[{"id":1,"name":"Mr. Nice"},{"id":2,"name":"Narco"},{"id":3,"name":"Bombasto"},{"id":4,"name":"Celeritas"},{"id":5,"name":"Magneta"},{"id":6,"name":"Super Adueduct"},{"id":7,"name":"Mr. Test"}]
Эта полная страница флаттера (которая была разделена на собственный маршрут) выглядит следующим образом:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<PostsList> fetchPostsList() async {
final response =
await http.get('http://localhost:8888/heroes');
if (response.statusCode == 200) {
return PostsList.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load post');
}
}
class PostsList {
final List<Post> posts;
PostsList({
this.posts,
});
factory PostsList.fromJson(List<dynamic> parsedJson) {
List<Post> posts = new List<Post>();
posts = parsedJson.map((i)=>Post.fromJson(i)).toList();
return new PostsList(
posts: posts
);
}
}
class Post{
final String id;
final String name;
Post({
this.id,
this.name
});
factory Post.fromJson(Map<String, dynamic> json){
return new Post(
id: json['id'].toString(),
name: json['name'],
);
}
}
class HeroesPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
home: Scaffold(
appBar: AppBar(
title: Text('Fetch Data Example'),
),
body: Center(
child: FutureBuilder<PostsList>(
future: fetchPostsList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
for(var i = 0; i < snapshot.data.posts.length; i++){
return Text(snapshot.data.posts[i].name + " - " +
snapshot.data.posts[i].id + " - " + i.toString());
}
//return Text(snapshot.data.posts[1].name);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner
return CircularProgressIndicator();
},
),
),
),
);
}
Теперь я могу неправильно отображать простые данные API, просто трудно найти учебник, не основанный на Firebase, работающий с флаттером и API.
К вашему сведению - API, работающий на локальном хосте, был настроен с помощью Aqueduct, следуя этому руководству: https://aqueduct.io/docs/tut/getting-started/
Код и его классификация основаны на руководстве по Flutter docs (пока немного измененном для моей структуры json): https://flutter.io/cookbook/networking/fetch-data/
1 ответ
Ты действительно близко! Проблема в том, что вы возвращаете цикл for внутри FutureBuilder builder
функция. Возврат прерывается из цикла после первой итерации, поэтому вы получите только первый элемент ваших данных.
Вместо этого вам нужно сгенерировать список всех виджетов в данных, а затем вернуть список.
Я могу подумать о двух возможных способах решения этой проблемы (зависит от желаемого виджета отображения):
=> Используйте ListView.builder для обработки итерации для вас:
if (snapshot.hasData) {
List<Post> yourPosts = snapshot.data.posts;
return ListView.builder(
itemCount: yourPosts.length,
itemBuilder: (BuildContext context, int index) {
// Whatever sort of things you want to build
// with your Post object at yourPosts[index]:
return Text(yourPosts[index].toString());
}
);
}
=> Построить List<Widget>
и вернуть столбец (ближайший к вашему первоначальному подходу):
if (snapshot.hasData) {
List <Widget> myPosts;
for(var i = 0; i < snapshot.data.posts.length; i++){
myPosts.add(Text(snapshot.data.posts[i].name + " - " +
snapshot.data.posts[i].id + " - " + i.toString())
);
}
return Column( children: myPosts );
}