It is confusing to me because the url shows that it is a string, since it is obviously an image. here it tells me that it expects a value of type int I don't understand what value is the integer. if the image expects a url of type string
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import '../models/catdata.dart';
class Apicat extends StatefulWidget {
Apicat({Key? key}) : super(key: key);
@override
State<Apicat> createState() => _ApicatState();
}
class _ApicatState extends State<Apicat> {
Future<List<CatData>> fetchCatdata() async {
final response = await http.get(Uri.parse(
'https://api.thecatapi.com/v1/images/search?limit=22&breed_ids=beng&api_key=f9891ce2-f1db-425d-bed0-0dcc1eb8be97'));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
final data = jsonDecode(response.body);
// este es un array de Strings
final list = data['url'] as List;
//final list2 = data['origin'] as List;
// pasa la data a objetos catData, recorriendo los strings y transformandolos a objeto
//final listCatData = list.map((item) => CatData(imagen: item)).toList();
return list.map((e) => CatData(imagen: e)).toList();
//return list.map((e) => CatData(imagen: e, origen: list2[0])).toList();
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
@override
Widget build(BuildContext context) {
return FutureBuilder<List<CatData>>(
future: fetchCatdata(),
builder: (BuildContext context, AsyncSnapshot<List<CatData>> snapshot) {
if (snapshot.hasData) {
//crea dos listas de catData, una para la imagen y otra para la descripcion
final list = snapshot.data!;
//final list2 = snapshot.data!;
return ListView.builder(
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return Image.network(list[index].imagen);
},
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner.
return CircularProgressIndicator();
},
);
}
}
and here the url https://api.thecatapi.com/v1/images/search?limit=22&breed_ids=beng&api_key=f9891ce2-f1db-425d-bed0-0dcc1eb8be97
here the class model
class CatData{
final String imagen;
CatData({required this.imagen});
factory CatData.fromJson(Map<String, dynamic> json) {
return CatData(
imagen: json['url'],
);
}
}
CodePudding user response:
The issue was using
final list = data['url'] as List;
. The response itself a list.
and providing list. To perse it do it like
if (response.statusCode == 200) {
final data = jsonDecode(response.body) as List;
return data.map((e) => CatData.fromMap(e)).toList();
}
Also I've modify the model class a little
class CatData {
final String imagen;
CatData({
required this.imagen,
});
Map<String, dynamic> toMap() {
final result = <String, dynamic>{};
result.addAll({'imagen': imagen});
return result;
}
factory CatData.fromMap(Map<String, dynamic> map) {
return CatData(
imagen: map['imagen'] ?? '',
);
}
String toJson() => json.encode(toMap());
factory CatData.fromJson(String source) =>
CatData.fromMap(json.decode(source));
}
This will give a little push on parsing
class Apicat extends StatefulWidget {
Apicat({Key? key}) : super(key: key);
@override
State<Apicat> createState() => _ApicatState();
}
class _ApicatState extends State<Apicat> {
Future<List<CatData>?> fetchCatdata() async {
final response = await http.get(
Uri.parse(
'https://api.thecatapi.com/v1/images/search?limit=2&breed_ids=beng&api_key=f9891ce2-f1db-425d-bed0-0dcc1eb8be97'),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body) as List;
return data.map((e) => CatData.fromMap(e)).toList();
} else {
throw Exception('Failed to load album');
}
}
late final future = fetchCatdata();
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<List<CatData>?>(
future: future,
builder: (BuildContext context, snapshot) {
if (snapshot.hasData) {
final list = snapshot.data!;
print(list);
return ListView.builder(
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return Image.network(list[index].imagen);
},
);
} else if (snapshot.hasError) {
return Text("Error ${snapshot.stackTrace}");
}
// By default, show a loading spinner.
return CircularProgressIndicator();
},
),
);
}
}
CodePudding user response:
Let's see. Your problem is the api returns a list of data and you want to take the url of all the children on the list, so to do that you need to convert the json response to a list, then you can take the url by adding these three lines.
final data = jsonDecode(response.body) as List<dynamic>;
final List<CatData> list = data.map((e) => CatData(imagen: e['url'])).toList();
return list;