State management in flutter application is crucial point while developing large scale application. Flutter has different state management techniques but in this post we are covering Bloc pattern to state management while calling the rest api.
Business Logic Component is google provided state management system in flutter abbreviated as Bloc. This bloc pattern encapsulate business logic from UI. Every Bloc component will have three blocs
Advantages of Bloc
Disadvantages
In this flutter application we will rest api with bloc state management. Here we are calling the Movie Albums Json API and fetch albums details and render on the UI. While Fetching the data from the network we will manage the state by loading indicator, once we fetched complete data from the API we will show albums data on the list by passing the data by bloc state class.
Let's get started
Step 1: Create Flutter application
Step 2: Add required dependencies to pubspec.yaml file, here we have used below dependencies
dependencies:
flutter:
sdk: flutter
http: ^0.13.3
equatable: ^2.0.3
flutter_bloc: ^7.0.1
|
http: For Call API requests
equatable : To compare objects while using bloc
flutter_bloc: To Manage state with bloc
Step 3: Here we are getting the albums so create a data model class with Response data from the api. For this creating the model class we will copy json response and paste in quicktype tool. this will give us model class which will contains the logic to convert json to model object.
our model class will be like this
We can parse json data with Model classes. We will pass the json string to json.decode() method then from the model class we will parse it.
import 'dart:convert';
List<Albums> albumsFromJson(String str) => List<Albums>.from(json.decode(str).map((x) => Albums.fromJson(x)));
String albumsToJson(List<Albums> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Albums {
Albums({
required this.userId,
required this.id,
required this.title,
});
late int userId;
late int id;
late String title;
factory Albums.fromJson(Map<String, dynamic> json) => Albums(
userId: json["userId"],
id: json["id"],
title: json["title"],
);
Map<String, dynamic> toJson() => {
"userId": userId,
"id": id,
"title": title,
};
}
|
Step 4: Create Service Layer to connect server and fetch data from server
Here created two files one is API Service class and other is repository class
service_api.dart file will be like this. We are calling the api with http get method and fetch http response and pass it to model class to create list of albums data
import 'package:flutter_api_with_bloc/model/album_model.dart';
import 'package:http/http.dart' as http;
abstract class ServiceApi{
Future<List<Albums>>getAlbums();
}
class AlbumService extends ServiceApi{
String BASE_URL="https://jsonplaceholder.typicode.com";
String ALBUMS="/albums";
@override
Future<List<Albums>> getAlbums() async{
try {
var uri = Uri.parse("https://jsonplaceholder.typicode.com/albums");
var response = await http.get(
uri, headers: {"ContentType": "application/json"});
var albumslist = albumsFromJson(response.body);
return albumslist;
} catch(e){
return List<Albums>.empty();
}
}
}
|
Step 5: Create bloc
We know that every bloc will contains three class bloc, state and event. let's create these class like below
albums_block.dart
import 'dart:io';
import 'album_state.dart';
import 'package:flutter_api_with_bloc/bloc/album/albums_events.dart';
import 'package:flutter_api_with_bloc/model/album_model.dart';
import 'package:flutter_api_with_bloc/repositories/Albumsrepository.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class AlbumsBloc extends Bloc<AlbumEvents,AlbumsState>
{
final Albumsrepository albumsrepository;
late List<Albums> listAlbums;
AlbumsBloc({required this.albumsrepository}) : super(AlbumInitialState());
@override
Stream<AlbumsState> mapEventToState(AlbumEvents event) async* {
switch(event)
{
case AlbumEvents.fetchAlbums:
yield AlbumLoadingState();
try {
listAlbums = await albumsrepository.getAlbumsList();
yield AlbumLoadedState(albums: listAlbums);
}on SocketException {
yield AlbumListErrorstate(
error: ('No Internet'),
);
} on HttpException {
yield AlbumListErrorstate(
error: ('No Service'),
);
} on FormatException {
yield AlbumListErrorstate(
error: ('No Format Exception'),
);
} catch (e) {
print(e.toString());
yield AlbumListErrorstate(
error: ('Un Known Error ${e.toString()}'),
);
}
break;
}
}
}
|
albums_state.dart
here to fetch api data and display we will create below states
AlbumInitialState : Before calling the API
AlbumLoadingState : While calling the API
AlbumLoadedState : After fetch the data from API
AlbumListErrorstate : If we receive error on Data
import 'package:equatable/equatable.dart';
import 'package:flutter_api_with_bloc/model/album_model.dart';
abstract class AlbumsState extends Equatable{
@override
// TODO: implement props
List<Object?> get props => [];
}
class AlbumLoadingState extends AlbumsState{ }
class AlbumInitialState extends AlbumsState{ }
class AlbumLoadedState extends AlbumsState{
final List<Albums> albums;
AlbumLoadedState({required this.albums});
}
class AlbumListErrorstate extends AlbumsState{
final error;
AlbumListErrorstate({this.error});
}
|
albums_event.dart
we have only one event, that is fetch albums from server. so we created one event like below
enum AlbumEvents{
fetchAlbums
}
|
Step 6: We are ready with Bloc and Service layer, now its time to handle UI. To Communicate UI with Service layer we will use BlocProvider This BlockProvider will contains two properties one for create bloc and other is child to pass your widgets
BlocProvider(create: (context)=>AlbumsBloc(albumsrepository: Albumsrepository()),
child:AlbumClass())
|
Step 7: Create Widget to display albums list
albums.dart
import 'package:flutter/material.dart';
import 'package:flutter_api_with_bloc/bloc/theme/themek_bloc.dart';
import 'package:flutter_api_with_bloc/themes/app_theme.dart';
import '../bloc/album/album_state.dart';
import '../bloc/album/albums_block.dart';
import 'package:flutter_api_with_bloc/bloc/album/albums_events.dart';
import 'package:flutter_api_with_bloc/model/album_model.dart';
import 'package:flutter_api_with_bloc/repositories/Albumsrepository.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class AlbumClass extends StatefulWidget{
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return AlbumClassState();
}
}
class AlbumClassState extends State<AlbumClass>{
bool isdark=true;
@override
void initState() {
// TODO: implement initState
super.initState();
loadAlbums();
}
loadAlbums() async
{
context.read<AlbumsBloc>().add(AlbumEvents.fetchAlbums);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(actions: [
Switch(
value: isdark,
onChanged: (val) async {
_setTheme(val);
isdark=!isdark;
},
)
],),
body: BlocBuilder<AlbumsBloc,AlbumsState>(builder: (BuildContext contex,AlbumsState state){
if (state is AlbumListErrorstate) {
final error = state.error;
String message = '${error.message}\nTap to Retry.';
return Text(
message,
);
}
if (state is AlbumLoadedState) {
List<Albums> albums = state.albums;
return _list(albums);
}
return Center(child: CircularProgressIndicator(),);
}),
);
}
Widget _list(List<Albums> albums) {
return ListView.builder(
itemCount: albums.length,
itemBuilder: (_, index) {
Albums album = albums[index];
return Container(
padding: EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: Text(
album.title,
style: TextStyle(
fontSize: 20,
color: Theme.of(context).textTheme.bodyText1!.color,
),
),
),
Divider(color: Theme.of(context).textTheme.bodyText1!.color,),
],
),
);;
},
);
}
_setTheme(bool darkTheme) async {
AppTheme selectedTheme =
darkTheme ? AppTheme.lightTheme : AppTheme.darkTheme;
print(darkTheme);
context.read<ThemekBloc>().add(ThemekEvent(appTheme: selectedTheme));
//Preferences.saveTheme(selectedTheme);
}
}
|
Step 8: Run application
Conclusion: In this flutter example we covered how to create bloc and fetch data from rest API and parse json data to display it on the UI with manage the state.
Article Contributed By :
|
|
|
|
7443 Views |