0 purchases
bloc rest api
Bloc REST API #
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
FYI: This package works on all platforms (Android, iOS, Web, Linux, Windows, Mac).
Usage #
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
dependencies:
bloc_rest_api: <latest version>
copied to clipboard
Next, we need to install it:
# Dart
pub get
# Flutter
flutter packages get
copied to clipboard
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
Note: Don't forget to use Equatable or any other comparision method to compare the models as it is the decision maker when it comes to switching state in bloc
In our case we'll be creating a model for Post.
import 'package:equatable/equatable.dart';
class PostModel extends Equatable {
PostModel({
this.userId,
this.id,
this.title,
this.body,
});
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,
};
@override
List<Object> get props => [userId, id];
}
copied to clipboard
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.
MultiBlocProvider(
providers: [
// for single model
BlocProvider(
create: (context) => RequestCubit<PostModel>(
fromMap: (json) => PostModel.fromJson(json),
),
),
// for list of posts simply update type and fromMap method
BlocProvider(
create: (context) => RequestCubit<List<PostModel>>(
fromMap: (json) =>
List<PostModel>.from(json.map((x) => PostModel.fromJson(x))),
),
),
],
child: AppView(),
);
copied to clipboard
To use the getRequest or postRequest methods simply use the context.read() funtion like:
context.read<RequestCubit<PostModel>>().getRequest(
baseUrl: 'https://jsonplaceholder.typicode.com/',
handle: 'posts/1',
);
copied to clipboard
You can also enable logs for requests in order to view logs happening for a specific function by setting enableLogs flag to true.
context.read<RequestCubit<PostModel>>().getRequest(
...
enableLogs: true,
);
copied to clipboard
Want to use local json strings? Don't worry the package got you covered.
context.read<RequestCubit<PostModel>>().localRequest(
'json string here',
);
copied to clipboard
Note: You can always convert local json file to string using loadString('path/to/asset') from import 'package:flutter/services.dart'
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('https://jsonplaceholder.typicode.com/posts/1');
if (response.statusCode == 200) {
return PostModel.fromJson(jsonDecode(response.body));
} else {
// Any exception thrown will emit failure state
throw Exception('Failed to load album');
}
}
...
context.read<RequestCubit<PostModel>>().request(fetchAlbum());
...
copied to clipboard
Finally react on the states by using either BlocBuilder, BlocListner or BlocConsumer method.
States can have one of 4 status distinguished as state.status:
RequestStatus.empty: Initial State
RequestStatus.loading: Loading State
RequestStatus.success: Success State
RequestStatus.error: Error State
Note: The state retains the data on status change and is only changed either on the success state or by explicitly calling the emptyCubit method. This features allows you to show previous data even on API error.
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));
default:
return Container();
}
},
),
copied to clipboard
ApiConfig
baseUrl, header and responseTimeOut can also be configured globally for all RequestCubit instances via ApiConfig
ApiConfig.baseUrl = '...';
ApiConfig.header = {'...': ''};
ApiConfig.responseTimeOut = Duration(...);
copied to clipboard
Other Userful Methods
You can use the updateModel method to update the state model manually.
context.read<RequestCubit<PostModel>>().updateModel(model);
copied to clipboard
Also you can empty or reinitialize the state using empty() method.
context.read<RequestCubit<PostModel>>().emtpy();
copied to clipboard
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.
BlocProvider(
create: (context) => HydratedRequestCubit<PostModel>(
fromMap: (json) => PostModel.fromJson(json),
toMap: (model) => model.toJson(),
),
),
copied to clipboard
And also initialize the storage
void main() async {
WidgetsFlutterBinding.ensureInitialized();
HydratedBloc.storage = await HydratedStorage.build();
runApp(App());
}
copied to clipboard
And now you're state will never go away. :)
Maintainers #
Muhammad Idrees
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.