This project demonstrates how to use Retrofit and Dio in a Flutter app for making clean and scalable API requests. This guide is beginner-friendly and covers all necessary steps including GET, POST, PUT, DELETE, PATCH, and Query Parameters usage.
Add the generator to your dev dependencies
dependencies:
retrofit: ^x.x.x
dio: ^x.x.x
dev_dependencies:
retrofit_generator: ^x.x.x
build_runner: ^x.x.x
import 'package:dio/dio.dart';
import 'package:learn_retrofit_dio/models/models.dart';
import 'package:retrofit/retrofit.dart';
import '../models/fetch_user_model/fetch_all_user_list_model.dart';
part 'api_services.g.dart';
@RestApi(baseUrl: 'https://reqres.in/')
abstract class ApiServices {
factory ApiServices(Dio dio, {String? baseUrl}) = _ApiServices;
// Fetch all user
@GET('api/users?page=2')
Future<UserList> getUserList();
// Fetch single user
@GET('api/users/{id}')
Future<SingleUserModel> getSingleUser(
@Header('x-api-key') String apiKey,
@Path('id') String id,
);
// Create a user
@POST('api/users')
Future<CreateUserShowModel> createUser(
@Header('x-api-key') String apiKey,
@Body() CreateUserRequestModel request,
);
}
Use this tool to convert JSON to Dart: Json to Dart Converter
import 'package:dio/dio.dart';
import 'package:learn_retrofit_dio/network/api_services.dart';
final apiServices = ApiServices(Dio());
dart pub run build_runner build
import 'package:flutter/material.dart';
import '../models/fetch_user_model/fetch_all_user_list_model.dart';
import '/config/config.dart';
import 'widget/widget.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
UserList userList = UserList();
bool isLoading = true;
UserRepository userRepo = UserRepository.userRepository;
@override
void initState() {
super.initState();
fetchUsers();
}
Future<void> fetchUsers() async {
final fetchedList = await userRepo.fetchAllUserList();
setState(() {
userList = fetchedList;
isLoading = false;
});
}
void showUserDetails(String userId) {
showDialog(
context: context,
builder: (context) => UserDetailsShowDialog(userId: userId),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Retrofit API')),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child:
isLoading
? Center(child: CircularProgressIndicator())
: RefreshIndicator(
onRefresh: userRepo.fetchAllUserList,
child: ListView.builder(
itemCount: userList.data?.length ?? 0,
itemBuilder: (context, index) {
final user = userList.data![index];
return InkWell(
onTap: () {
showUserDetails(user.id.toString());
},
child: ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(
user.avatar.toString(),
),
),
title: Text(user.firstName.toString()),
subtitle: Text(user.email.toString()),
),
);
},
),
),
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
Spacer(),
ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (context) => CreateUserDialog(),
);
},
child: Text('Create User'),
),
],
),
],
),
),
);
}
}
@GET('api/users')
Future UserList getUserList(@Query('page') int page);
// Usage:
final userList = await apiServices.getUserList(2);
@GET('api/users/{id}')
Future dynamic getSingleUser(@Path('id') String id);
// Usage:
final user = await apiServices.getSingleUser('2');
@POST('api/users')
Future dynamic createUser(@Body() Map String, dynamic body);
// Usage:
final response = await apiServices.createUser({
'name': 'John Doe',
'job': 'Developer',
});
@PUT('api/users/{id}')
Future dynamic updateUser(@Path('id') String id, @Body() Map String, dynamic body);
// Usage:
final response = await apiServices.updateUser('2', {
'name': 'Jane Doe',
'job': 'Manager',
});
@PATCH('api/users/{id}')
Future dynamic patchUser(@Path('id') String id, @Body() Map String, dynamic body);
// Usage:
final response = await apiServices.patchUser('2', {
'job': 'Lead Developer',
});
@DELETE('api/users/{id}')
Future dynamic deleteUser(@Path('id') String id);
// Usage:
final response = await apiServices.deleteUser('2');
@GET('api/users')
Future UserList getUserListWithQuery(@Queries() Map String, dynamic queries);
// Usage:
final userList = await apiServices.getUserListWithQuery({
'page': 2,
'per_page': 5,
});
- β Retrofit makes HTTP API calls easier and cleaner in Flutter.
- β Dio handles network operations efficiently with options for logging, interceptors, and more.
- β You can handle GET, POST, PUT, PATCH, DELETE, and use Query/Path parameters using Retrofit decorators.
β Happy Coding!