A flutter package to easily integrate and manage REST APIs. Now all you need to do is create a model class and all the rest is taken care of. :)

Before using the package fimiliarize yourself with bloc library


To demonstrate the usage of the package we'll be using JsonPlaceHolder

First, we need to do add bloc_rest_api to the dependencies of the pubspec.yaml

  bloc_rest_api: <latest version>

Next, we need to install it:

# Dart
pub get

# Flutter
flutter packages get

Now create a model class for the data that you want to fetch from the internet. This can easily be done by using online tools such as QuickType

In our case we'll be creating a model for Post.

import 'package:equatable/equatable.dart';

class PostModel extends Equatable {

  final int userId;
  final int id;
  final String title;
  final String body;

  factory PostModel.fromJson(Map<String, dynamic> json) => PostModel(
        userId: json["userId"] == null ? null : json["userId"],
        id: json["id"] == null ? null : json["id"],
        title: json["title"] == null ? null : json["title"],
        body: json["body"] == null ? null : json["body"],

  Map<String, dynamic> toJson() => {
        "userId": userId == null ? null : userId,
        "id": id == null ? null : id,
        "title": title == null ? null : title,
        "body": body == null ? null : body,

  List<Object> get props => [userId, id];

Now create a provider for RequestCubit of type model (in our case PostModel) and pass in the fromMap function i.e. the fucntion that converts the incoming json to model.

  providers: [
    // for single model
      create: (context) => RequestCubit<PostModel>(
        (json) => PostModel.fromJson(json),
    // for list of posts simply update type and fromMap method
      create: (context) => RequestCubit<List<PostModel>>(
        (json) =>
            List<PostModel>.from( => PostModel.fromJson(x))),
  child: AppView(),

To use the getRequest or postRequest methods simply use the funtion like:<RequestCubit<PostModel>>().getRequest(
      baseUrl: "",
      handle: "posts/1",

In case you are dealing with complex data and want to handle the mapping yourself you can you the request method that takes a function that returns Future of type T as parameter.

Future<PostModel> fetchAlbum() async {
  final response =
      await http.get('');

  if (response.statusCode == 200) {
    return PostModel.fromJson(jsonDecode(response.body));
  } else {
    // Any exception thrown will emit failure state
    throw Exception('Failed to load album');


Finally react on the states by using either BlocBuilder, BlocListner or BlocConsumer method.

States can be one of four and can be distinguished by state.status:

  1. RequestState.empty: Initial State
  2. RequestState.loading: Loading State
  3. RequestState.success: Success State
  4. RequestState.error: Error State

Heres is an example builder method for PostModel:

BlocBuilder<RequestCubit<PostModel>, RequestState<PostModel>>(
  builder: (context, state) {
    switch (state.status) {
      case RequestStatus.empty:
        return Center(child: Text("Press the button to get some data"));

      case RequestStatus.loading:
        return Center(child: CircularProgressIndicator());

      case RequestStatus.success:
        return Center(
          child: Padding(
            padding: const EdgeInsets.all(32.0),
            child: Text(state.model.toString()),

      case RequestStatus.failure:
        return Center(child: Text(state.errorMessage));
        return Container();


baseUrl, header and responseTimeOut can also be configured globally for all RequestCubit instances via ApiConfig

ApiConfig.baseUrl = "...";
ApiConfig.header = {"...": ""};
ApiConfig.responseTimeOut = Duration(...);

Other Userful Methods

You can use the updateModel method to update the state model manually.<RequestCubit<PostModel>>().updateModel(model);

Also you can empty or reinitialize the state using empty() method.<RequestCubit<PostModel>>().emtpy();

Presisting REST APIs

Sometimes you want to presist the api data. For that you can simply replace the RequestCubit to HydratedRequestCubit.

Just make sure to provide fromMap and toMap functions in the provider.

  create: (context) => HydratedRequestCubit<PostModel>(
    fromMap: (json) => PostModel.fromJson(json),
    toMap: (model) => model.toJson(),

And also initialize the storage

void main() async {
  WidgetsFlutterBinding.ensureInitialized(); = await;

And now you're state will never go away. :)