30
loading...
This website collects cookies to deliver better user experience
Note: This tutorial focuses on how it works. To keep it easy, I'll place all the code in the main.dart file.
flutter pub add http
main.dart
file.import 'package:http/http.dart' as http;
https://api.jikan.moe/v3/top/anime/1
{
"request_hash": "request:top:58399c95e55435d6ccef63eef7ce609974e4f2d5",
"request_cached":true,
"request_cache_expiry":77456,
"top":[
{
"mal_id":5114,
"rank":1,
"title":"Fullmetal Alchemist: Brotherhood",
"url":"https:\/\/myanimelist.net\/anime\/5114\/Fullmetal_Alchemist__Brotherhood",
"image_url":"https:\/\/cdn.myanimelist.net\/images\/anime\/1223\/96541.jpg?s=faffcb677a5eacd17bf761edd78bfb3f",
"type":"TV",
"episodes":64,
"start_date":"Apr 2009",
"end_date":"Jul 2010",
"members":2504975,
"score":9.17
},
{
...
}
]
}
top
items, this is the actual data set, and it comes as an array of objects.Show
class to map some of this data that we can use for our app.class Show {
final int malId;
final String title;
final String imageUrl;
final double score;
Show({
required this.malId,
required this.title,
required this.imageUrl,
required this.score,
});
factory Show.fromJson(Map<String, dynamic> json) {
return Show(
malId: json['mal_id'],
title: json['title'],
imageUrl: json['image_url'],
score: json['score'],
);
}
}
Show,
and we define the variables it has. In our case, we only need those described.Future<List<Show>> fetchShows() async {
final response =
await http.get(Uri.parse('https://api.jikan.moe/v3/top/anime/1'));
if (response.statusCode == 200) {
var topShowsJson = jsonDecode(response.body)['top'] as List;
return topShowsJson.map((show) => Show.fromJson(show)).toList();
} else {
throw Exception('Failed to load shows');
}
}
void main() async {
runApp(AnimeApp());
}
class AnimeApp extends StatefulWidget {
AnimeApp({Key? key}) : super(key: key);
@override
_AnimeAppState createState() => _AnimeAppState();
}
class _AnimeAppState extends State<AnimeApp> {
late Future<List<Show>> shows;
@override
void initState() {
super.initState();
shows = fetchShows();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Anime app',
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(title: Text('Anime app')),
body: Center(
// TODO
)
),
);
}
}
child: FutureBuilder(
builder: (context, AsyncSnapshot<List<Show>> snapshot) {
if (snapshot.hasData) {
// TODO
} else if (snapshot.hasError) {
return Center(child: Text('Something went wrong :('));
}
return CircularProgressIndicator();
},
future: shows,
),
hasData
variable is set. If so, we can render this data!return Center(
child: ListView.separated(
padding: const EdgeInsets.all(8),
itemCount: snapshot.data!.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundImage:
NetworkImage('${snapshot.data?[index].imageUrl}'),
),
title: Text('${snapshot.data?[index].title}'),
subtitle: Text('Score: ${snapshot.data?[index].score}'),
);
},
separatorBuilder: (BuildContext context, int index) =>
const Divider(),
),
);
ListTile
widget containing the avatar, title, and score.