Rxdart — BlocPattern-API call in Flutter

Daya Nithi
4 min readDec 3, 2019

--

Today we are going to see about how to use rx-dart in flutter using Bloc pattern.

As far I consider Bloc pattern is nothing but a MVVM pattern in android. So read MVVM pattern if you need to explore more in that field.

Add below two lines in your pubspec.yaml under dependencies

rxdart: ^0.18.0

http: ^0.12.0+2

Next consider using package like this because it will be easy to discuss

Let us consider we will be showing a parameter of IOT.

  1. Under API Model package create a class named ParameterDetailApiModel.dart

Which Is a model class helps us to parse the json from url.

2. Under ApiService Package create Urls.dart class

Which will hold all urls and api calls to the server.

3. Under blocs package add ParameterDetailBloc.dart

Which will hold rx-dart subjects.

4. Under resources Package add Repository.dart

Which will async process the api call and UI update.

Create a stateful widget

class ParameterDetail extends StatefulWidget {
String dataId;

ParameterDetail(String DataId) {
dataId = DataId;
}

@override
State<StatefulWidget> createState() {
// TODO: implement createState

return ParameterDetailState(dataId);
}
}

Next create a state for that widget. You are passing the data ID to query to the server using constructor.

class ParameterDetailState extends State<ParameterDetail> {
String dataId;

ParameterDetailState(String DataId) {
this.dataId = DataId;
}

@override
initState() {
blocDetail.fetchAllParameter(dataId);
}

Next under init state. We have to initialize the bloc to fetch the data. I will explain it later.

@override
Widget build(BuildContext context) {
// TODO: implement build
Container main = Container(
child: StreamBuilder(
stream: blocDetail.allParameter,
builder: (context, AsyncSnapshot<ParameterDetailApiModel> snapshot) {
if (snapshot.hasData) {

Under the main widget add a child which is a StreamBuilder widget.

A Stream Builder widget usually contains a stream and builder parameter.

Now we have to listen to the stream which is blocDetail.allParameter.

Inside builder. Pass your context and custom model class and has a variable snapshot.

Inside the snapshot all our values will be present.

Details of model class

class ParameterDetailApiModel {

String Zone = “”;
String EquipmentName = “”;
String Customer = “”;
String Location = “”;
String RunHours = “”;
String Lattitude = “”;
String Longitude = “”;
String ReceivedGMT = “”;

ParameterDetailApiModel(
{

this.Zone,
this.EquipmentName,
this.Location,
this.RunHours,
this.Customer,
this.Lattitude,
this.Longitude,
this.ReceivedGMT});

factory ParameterDetailApiModel.formJson(Map<String, dynamic> parsedJson) {
return ParameterDetailApiModel(
Zone: parsedJson[“Zone”],
EquipmentName: parsedJson[“EquipmentName”],
Customer: parsedJson[“Customer”],
Location: parsedJson[“Location”],
RunHours: parsedJson[“RunHours”],
Lattitude: parsedJson[“Lattitude”],
Longitude: parsedJson[“Longitude”],
ReceivedGMT: parsedJson[“ReceivedGMT”]);
}

}

Under ApiService in Urls.dart

Future<ParameterDetailApiModel> getParameterBasedOnId(String DataId) async {
var queryparams = {
‘DataId’: DataId,
};
var uri = Uri.http(‘${Urls.BaseUrl}’, ‘/your_path/get_parameter’, queryparams);
print(uri);
final response = await http.get(
uri,
headers: {“Accept”: “application/json”},
);
if (response.statusCode == 200) {
print(json.decode(response.body));
return ParameterDetailApiModel.formJson(json.decode(response.body));
} else {
return null;
}
}

Now you are ready to receive the api call. In the above code we can see that we have used it only to call the api from server.

Now the best part is to use the bloc pattern

class ParameterDetailBloc {
final _repository = Repository();
final _Rx_onUpdateParameterDetailLister =
PublishSubject<ParameterDetailApiModel>();

Observable<ParameterDetailApiModel> get allParameter =>
_Rx_onUpdateParameterDetailLister.stream;

fetchAllParameter(String dataId) async {
ParameterDetailApiModel model =
await _repository.getParameterBasedOnId(dataId);
_Rx_onUpdateParameterDetailLister.sink.add(model);
}

dispose() {
_Rx_onUpdateParameterDetailLister.close();
}
}

final blocDetail = ParameterDetailBloc();

Now initialize the repository

Create a publish subject with the model you want to publish.

final _Rx_onUpdateParameterDetailLister =
PublishSubject<ParameterDetailApiModel>();

Create a Observable stream which put the data into the stream. This is use to get the value as stream.

Observable<ParameterDetailApiModel> get allParameter =>
_Rx_onUpdateParameterDetailLister.stream;

Here we fetch the api call and post it to the stream

fetchAllParameter(String dataId) async {
ParameterDetailApiModel model =
await _repository.getParameterBasedOnId(dataId);
_Rx_onUpdateParameterDetailLister.sink.add(model);
}

Finally we dispose it from the main page.

dispose() {
_Rx_onUpdateParameterDetailLister.close();
}

This will return the blocdetail class.

final blocDetail = ParameterDetailBloc();

This will be your final class

@override
Widget build(BuildContext context) {
// TODO: implement build
Container main = Container(
child: StreamBuilder(
stream: blocDetail.allParameter,
builder: (context, AsyncSnapshot<ParameterDetailApiModel> snapshot) {
if (snapshot.hasData) {
if (isExpanded == false) {
return Row(children: <Widget>[
Text(“Equipment Name “ + snapshot.data.EquipmentName),
new FlatButton(
onPressed: () {
setState(() {
isExpanded = true;
});
},
child: Image.asset(
“assets/images/sort.png”,
height: 30,
width: 30,
),
),
]);
}

Here for complexity reasons I have used only TextView to show the data

Text(“Equipment Name “ + snapshot.data.EquipmentName),

Always you should access data using data.{“Your_data”}

Hurrah!!! we have learned the Bloc pattern in flutter using API call.

Repository class:

class Repository {
final apiProvider = APIService();

Future<EquipmentListerApiModel> getEquipmentLister(String customerId) =>
apiProvider.getEquipmentLister(customerId);
}

Inside resources package, we create a Repository class.

We call the APIService initially.

Then we create a method getEquipmentLister and pass customerId as value and use apiProvider.getEquipmentLister we call the API in APIservice class.

Which in term returns a future object . In our case Future<EquipmentListerApiModel>. Then we receive this in the mainclass and parse it and use it.

--

--

Daya Nithi

6+ years of development of android applications. Exploring Flutter and more to come.