backfit 0.0.2+8
backfit: ^0.0.2+8 copied to clipboard
Retrofit inspired HTTP Client generator for Dart
Backfit #
Backfit is a Retrofit inspired HTTP Client and API Service generator for Dart. This package works with its companion package called backfit.
Installation #
Add the following to pubspec.yaml
dependencies:
backfit: <latest_version>
dev_dependencies:
backfit_generator: <latest_version>
build_runner: <latest_version>
Usage #
First create a BackFit client
import 'package:backfit/backfit.dart';
final client = BackfitClient(
baseUrl: 'https://jsonplaceholder.typicode.com',
interceptors: [HttpLogger()]);
Then create an interface annotated with BackfitService
annotation, it takes base end point as an optional parameter.
posts_service.dart
import 'package:backfit/backfit.dart';
part 'posts_service.backfit.dart';
@BackfitService()
abstract class Posts {}
As per your API requirement create a model with serialization support. In this example, I am using freezed
and json_serializable
for it, however these are not necessary. You just need a toJson()
method and fromJson
factory or static method inside the model class
my_post.dart
import 'package:freezed_annotation/freezed_annotation.dart';
part 'my_post.freezed.dart';
part 'my_post.g.dart';
@freezed
class MyPost with _$MyPost {
const factory MyPost({
required int userId,
required int id,
required String title,
required String body,
}) = _MyPost;
factory MyPost.fromJson(Map<String, dynamic> json) => _$MyPostFromJson(json);
}
Now go back to the api_service interface and add an abstract method defining the return type, endpoint and signature.
posts_service.dart
import 'package:backfit/backfit.dart';
import 'my_post.dart';
part 'posts_service.backfit.dart';
@BackfitService()
abstract class Posts {
@Get('posts')
Future<Response<List<MyPost>>> postsByUserId(@Query('userId') String userId);
}
Note that the Response class mentioned here is from Backfit
and not http
and as such takes in your Model class as a type parameter for auto parsing.
Now if you are using flutter run -
flutter pub run build_runner [build|watch] [OPTIONAL --delete-conflicting-outputs]
Or if you are working with dart only run -
pub run build_runner [build|watch] [OPTIONAL --delete-conflicting-outputs]
This generates the following code -
posts_service.backfit.dart
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'posts_service.dart';
// **************************************************************************
// BackfitGenerator
// **************************************************************************
class PostsService extends Posts with _$Posts {
PostsService() {
_client = BackfitClient();
}
PostsService.withClient(BackfitClient client) {
_client = client;
}
}
mixin _$Posts implements Posts {
BackfitClient? _client;
@override
Future<Response<List<MyPost>>> postsByUserId(String userId) async {
final res = await _client!
.get(Uri.parse('${_client!.baseUrl}/posts/posts?userId=$userId'));
return Response(
data: res.body.isNotEmpty
? (json.decode(res.body) as List)
.map((it) => MyPost.fromJson(it))
.toList()
: null,
statusCode: res.statusCode,
reasonPhrase: res.reasonPhrase,
headers: HttpHeaders.fromMap(res.headers),
);
}
}
What's Next? Consume the Api Service wherever you want like this -
//in some injector
final postsService = PostsService.withClient(client);
//inside a consumer
postsService.postsByUserId('1').catchError((e) {
print(e.toString());
});
Contributing #
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.