In the mobile app development lifecycle, communicating with the server(via API) to fetch or store data is one of the basic needs.
So, in today’s blog let’s check Retrofit API calling in a flutter.
I hope you’re all familiar with Android/iOS, and you’ve even heard of Retrofit and Alamofire.
Check out more about our Flutter app development.
We use network calls in almost every app, and they’ve become an integral part of app functioning.
To call Rest APIs by sending dynamic headers, parameters, print requests, and responses in a more custom and secure way “Retrofit” is the best solution.
Let’s start the steps for Retrofit API calling in a flutter
Step 1: Create a flutter project.
Step 2: Add the below dependencies in pubspec.yaml file
1 2 3 4 5 6 7 8 9 |
dependencies: retrofit: ^1.3.4+1 built_value: ^7.1.0 <span class="hljs-attr">logger:</span> <span class="hljs-string">any</span> <span class="hljs-comment">#for logging purpose</span> dev_dependencies: retrofit_generator: ^1.3.7+5 build_runner: ^1.10.0 built_value_generator: ^7.1.0 |
Now, run the command “flutter pub get” to download the dependencies.
Step 3: Now, let’s create an abstract API request class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import 'package:dio/dio.dart'; import 'package:flutter_app/Model/User.dart'; import 'package:retrofit/http.dart'; part 'api_client.g.dart'; @RestApi(baseUrl: "https://jsonplaceholder.typicode.com/") abstract class ApiClient { factory ApiClient(Dio dio, {String baseUrl}) = _ApiClient; @GET('todos/') Future<List<User>> getUsers(); @POST('user/Api/v1/user/login') //login Future<Response> getLogin([ @Header("DeviceId") String deviceId, @Header("AuthorizedToken") String authenticationKey, @Header("Version") String version, @QueryMap() Map<String, String> param, ]); } |
Right now, you will observe some errors in the file in “part ‘api_client.g.dart’ ” and _ApiClient.
We need to run a command and generate an “api_client.g.dart” file.
Step 4: Now run the command in the terminal
flutter pub run build_runner build
The above command will generate the api_client.g.dart file & contains all data about creating Retrofit instance and fetching data from the network.
You should never modify the code in api_client.g.dart file by hand.
If you made any changes in ApiClient then also run the command to update part file.
Step 5: Now, create a model class to store the API data.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
import 'dart:convert'; List<User> userFromJson(String str) => List<User>.from(json.decode(str).map((x) => User.fromJson(x))); String userToJson(List<User> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson()))); class User { User({ this.userId, this.id, this.title, this.completed, }); int userId; int id; String title; bool completed; factory User.fromJson(Map<String, dynamic> json) => User( userId: json["userId"], id: json["id"], title: json["title"], completed: json["completed"], ); Map<String, dynamic> toJson() => { "userId": userId, "id": id, "title": title, "completed": completed, }; } |
Step 6: Then, call the get method from your main.dart class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
FutureBuilder<List<User>> _buildBody(BuildContext context) { final client = ApiClient(Dio(BaseOptions(contentType: "application/json"))); return FutureBuilder<List<User>>( future: client.getUsers(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { final List<User> posts = snapshot.data; return _buildPosts(context, posts); } else { return Center( child: CircularProgressIndicator(), ); } }, ); } |
Please find below the complete code for main.dart class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
import 'dart:collection'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'Model/User.dart'; import 'Retrofit/api_client.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { // to set the root of app. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.green, visualDensity: VisualDensity.adaptivePlatformDensity, ), home: MyHomePage(title: 'API Demo Page'), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override void initState() { super.initState(); } Future getPostApiCall() async{ final client = ApiClient(Dio(BaseOptions(contentType: "application/json"))); Map<String, String> createDoc = new HashMap(); createDoc['username'] = "shikha"; createDoc['password'] = "shikha"; // final response = client.getLogin('123','abc','',createDoc); final response = client.getUsers(); final user = userFromJson(response.toString()); print(user); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar( title: Text("Flutter - Retrofit Implementation"), ), body: _buildBody(context), floatingActionButton: FloatingActionButton.extended( onPressed: () { }, label:Icon(Icons.cancel), backgroundColor: Colors.green, ), ); } // build list view & manage states FutureBuilder<List<User>> _buildBody(BuildContext context) { final client = ApiClient(Dio(BaseOptions(contentType: "application/json"))); return FutureBuilder<List<User>>( future: client.getUsers(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { final List<User> posts = snapshot.data; return _buildPosts(context, posts); } else { return Center( child: CircularProgressIndicator(), ); } }, ); } // build list view & its tile ListView _buildPosts(BuildContext context, List<User> posts) { return ListView.builder( itemCount: posts.length, padding: EdgeInsets.all(8), itemBuilder: (context, index) { return Card( elevation: 4, child: ListTile( title: Text( posts[index].title, style: TextStyle(fontWeight: FontWeight.bold), ), subtitle: Text(posts[index].completed.toString()), ), ); }, ); } } |
Finally, you can run the code, and see the below results.
For more details and methods you can refer to the doc here.
For more interesting blogs check out here – https://mobikul.com/blog/
Hope this blog helped you for a better understanding of Retrofit API calling in Flutter.
Thanks for reading 🙂