In this tutorial, we will be using http package for handling Rest API , when you are building UI in flutter you want to show some data from the backend.
Table of Contents
Importing dependencies in pubspec.yaml
http: ^0.13.1 photo_view: ^0.11.1 flutter_spinkit: ^5.0.0
Get request call
get request call using reqres api
final String apiUrl = "https://reqres.in/api/users?per_page=40"; Future<List<User>> fetchDataFromApi() async { Response res = await get(Uri.parse(apiUrl)); if (res.statusCode == 200) { Map body = jsonDecode(res.body); List<User> users = body['data'].map<User>((var item) => User.fromJson(item)).toList(); return users; } else { throw "Unable to retrieve posts."; } }
User Model for Deserialization
class User { int id; String email; String firstName; String lastName; String avatar; User({this.id, this.email, this.firstName, this.lastName, this.avatar}); User.fromJson(Map<String, dynamic> json) { id = json['id']; email = json['email']; firstName = json['first_name']; lastName = json['last_name']; avatar = json['avatar']; } Map<String, dynamic> toJson() { final Map<String, dynamic> data = new Map<String, dynamic>(); data['id'] = this.id; data['email'] = this.email; data['first_name'] = this.firstName; data['last_name'] = this.lastName; data['avatar'] = this.avatar; return data; } }
FutureBuilder with horizontal list
below example we will be working on horizontal list with future builder.
Container( height: 150.0, child: FutureBuilder<List<User>>( future: fetchDataFromApi(), builder: (context, userSnap) { if (userSnap.hasData) { return ListView.builder( itemCount: userSnap.data?.length, scrollDirection: Axis.horizontal, itemBuilder: (context, index) { User user = userSnap.data[index]; return GestureDetector( onTap: () { Navigator.of(context).push(MaterialPageRoute( builder: (_) => PhotoViewExample( imageUrl: user.avatar, name: '${user.firstName + "" + user.lastName}', ))); }, child: Card( elevation: 2, child: Container( width: MediaQuery.of(context).size.width / 2, color: Colors.primaries[ Random().nextInt(Colors.primaries.length)], child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( height: 50.0, width: 50.0, child: CircleAvatar( backgroundImage: NetworkImage(user.avatar), radius: 25.0, ), ), Text( '${user.firstName + "" + user.lastName}', style: TextStyle( fontSize: 20.0, color: Colors.white, ), ), Text( '${user.email}', //// style: TextStyle( fontSize: 15.0, color: Colors.white, fontStyle: FontStyle.italic, ), ), Text( '${user.id}', //// style: TextStyle( fontSize: 15.0, color: Colors.white, fontStyle: FontStyle.italic, ), ), ], ), ), ), ); }, ); } else if (userSnap.hasError) { return Text("${userSnap.error}"); } return SpinKitFadingCircle( itemBuilder: (_, int index) { return DecoratedBox( decoration: BoxDecoration( color: index.isEven ? Colors.red : Colors.green, ), ); }, size: 120.0, ); // return Center( // child: Container( // height: 50.0, // width: 50.0, // child: CircularProgressIndicator()), // ); }), ),
PhotoView Example
Here we created the photoview example
class PhotoViewExample extends StatefulWidget { final String imageUrl; final String name; const PhotoViewExample({Key key, this.imageUrl, this.name}) : super(key: key); @override _PhotoViewExampleState createState() => _PhotoViewExampleState(); } class _PhotoViewExampleState extends State<PhotoViewExample> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.name), centerTitle: true, ), body: Container( child: PhotoView( imageProvider: NetworkImage(widget.imageUrl), )), ); } }
Full source code
import 'dart:convert'; import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:http/http.dart' as http; import 'package:http/http.dart'; import 'package:http_requests/user.dart'; import 'package:photo_view/photo_view.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), debugShowCheckedModeBanner: false, home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { final String apiUrl = "https://reqres.in/api/users?per_page=40"; Future<List<User>> fetchDataFromApi() async { Response res = await get(Uri.parse(apiUrl)); if (res.statusCode == 200) { Map body = jsonDecode(res.body); List<User> users = body['data'].map<User>((var item) => User.fromJson(item)).toList(); return users; } else { throw "Unable to retrieve posts."; } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("HTTP GET REQUEST"), ), body: Padding( padding: const EdgeInsets.all(12.0), child: ListView( children: [ Container( padding: const EdgeInsets.all(12.0), child: Text( "#Header 1", style: Theme.of(context) .textTheme .headline4 .copyWith(fontWeight: FontWeight.bold), ), ), Container( height: 150.0, child: FutureBuilder<List<User>>( future: fetchDataFromApi(), builder: (context, userSnap) { if (userSnap.hasData) { return ListView.builder( itemCount: userSnap.data?.length, scrollDirection: Axis.horizontal, itemBuilder: (context, index) { User user = userSnap.data[index]; return GestureDetector( onTap: () { Navigator.of(context).push(MaterialPageRoute( builder: (_) => PhotoViewExample( imageUrl: user.avatar, name: '${user.firstName + "" + user.lastName}', ))); }, child: Card( elevation: 2, child: Container( width: MediaQuery.of(context).size.width / 2, color: Colors.primaries[ Random().nextInt(Colors.primaries.length)], child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( height: 50.0, width: 50.0, child: CircleAvatar( backgroundImage: NetworkImage(user.avatar), radius: 25.0, ), ), Text( '${user.firstName + "" + user.lastName}', style: TextStyle( fontSize: 20.0, color: Colors.white, ), ), Text( '${user.email}', //// style: TextStyle( fontSize: 15.0, color: Colors.white, fontStyle: FontStyle.italic, ), ), Text( '${user.id}', //// style: TextStyle( fontSize: 15.0, color: Colors.white, fontStyle: FontStyle.italic, ), ), ], ), ), ), ); }, ); } else if (userSnap.hasError) { return Text("${userSnap.error}"); } return SpinKitFadingCircle( itemBuilder: (_, int index) { return DecoratedBox( decoration: BoxDecoration( color: index.isEven ? Colors.red : Colors.green, ), ); }, size: 120.0, ); // return Center( // child: Container( // height: 50.0, // width: 50.0, // child: CircularProgressIndicator()), // ); }), ), Container( padding: const EdgeInsets.all(12.0), child: Text( "#Header 2", style: Theme.of(context) .textTheme .headline4 .copyWith(fontWeight: FontWeight.bold), ), ), Expanded( child: Container( height: 300.0, child: FutureBuilder<List<User>>( future: fetchDataFromApi(), builder: (context, userSnap) { if (userSnap.hasData) { return ListView.builder( itemCount: userSnap.data?.length, itemBuilder: (context, index) { User user = userSnap.data[index]; return Card( elevation: 2, child: ListTile( tileColor: Colors.primaries[ Random().nextInt(Colors.primaries.length)], title: Text( '${user.firstName + "" + user.lastName}', style: TextStyle( fontSize: 20.0, color: Colors.white, ), ), subtitle: Text( '${user.email}', //// style: TextStyle( fontSize: 15.0, color: Colors.white, fontStyle: FontStyle.italic, ), ), trailing: Text( '${user.id}', //// style: TextStyle( fontSize: 15.0, color: Colors.white, fontStyle: FontStyle.italic, ), ), leading: Column( children: <Widget>[ CircleAvatar( backgroundImage: NetworkImage(user.avatar), radius: 25.0, ) ], ), onTap: () { Navigator.of(context).push(MaterialPageRoute( builder: (_) => PhotoViewExample( imageUrl: user.avatar, name: '${user.firstName + "" + user.lastName}', ))); }, ), ); }, ); } else if (userSnap.hasError) { return Text("${userSnap.error}"); } return SpinKitFadingCircle( itemBuilder: (_, int index) { return DecoratedBox( decoration: BoxDecoration( color: index.isEven ? Colors.red : Colors.green, ), ); }, size: 120.0, ); // return Center( // child: Container( // height: 50.0, // width: 50.0, // child: CircularProgressIndicator()), // ); }), ), ), Flexible( child: Container( padding: const EdgeInsets.all(12.0), child: Text( "#Header 3", style: Theme.of(context) .textTheme .headline4 .copyWith(fontWeight: FontWeight.bold), ), ), ), Expanded( child: Container( height: 150.0, child: FutureBuilder<List<User>>( future: fetchDataFromApi(), builder: (context, userSnap) { if (userSnap.hasData) { return ListView.builder( itemCount: userSnap.data?.length, scrollDirection: Axis.horizontal, itemBuilder: (context, index) { User user = userSnap.data[index]; return GestureDetector( onTap: () { Navigator.of(context).push(MaterialPageRoute( builder: (_) => PhotoViewExample( imageUrl: user.avatar, name: '${user.firstName + "" + user.lastName}', ))); }, child: Card( elevation: 2, child: Container( width: MediaQuery.of(context).size.width / 2, color: Colors.primaries[Random() .nextInt(Colors.primaries.length)], child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( height: 50.0, width: 50.0, child: CircleAvatar( backgroundImage: NetworkImage(user.avatar), radius: 25.0, ), ), Text( '${user.firstName + "" + user.lastName}', style: TextStyle( fontSize: 20.0, color: Colors.white, ), ), Text( '${user.email}', //// style: TextStyle( fontSize: 15.0, color: Colors.white, fontStyle: FontStyle.italic, ), ), Text( '${user.id}', //// style: TextStyle( fontSize: 15.0, color: Colors.white, fontStyle: FontStyle.italic, ), ), ], ), ), ), ); }, ); } else if (userSnap.hasError) { return Text("${userSnap.error}"); } return SpinKitFadingCircle( itemBuilder: (_, int index) { return DecoratedBox( decoration: BoxDecoration( color: index.isEven ? Colors.red : Colors.green, ), ); }, size: 120.0, ); // return Center( // child: Container( // height: 50.0, // width: 50.0, // child: CircularProgressIndicator()), // ); }), ), ) ], ), ), ); } } class PhotoViewExample extends StatefulWidget { final String imageUrl; final String name; const PhotoViewExample({Key key, this.imageUrl, this.name}) : super(key: key); @override _PhotoViewExampleState createState() => _PhotoViewExampleState(); } class _PhotoViewExampleState extends State<PhotoViewExample> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.name), centerTitle: true, ), body: Container( child: PhotoView( imageProvider: NetworkImage(widget.imageUrl), )), ); } }
Conclusion
In this post, we are building a UI that contains horizontal and vertical list views on a single screen. Handling Rest API using HTTP package