Flutter: Getting Started with the BLoC Pattern, Streams & HTTP Request\Response
Tags: codenewbie, flutter, tutorial
Published: 2021-01-27 22:56:35


I mentioned in my previous post that I am learning Flutter to implement &  publish my App KidzTokenz on Apple App Store & so far, I am enjoying the experience, and I signed up for the #30DaysOfFlutter starting on Feb 1


{% twitter 1354272892184219648 %}

In this post, we are going to follow the BLoC pattern to integrate with the users API on [{JSON} Placeholder](https://jsonplaceholder.typicode.com/) and build an app to do the following:

* Use the [http package](https://pub.dev/packages/http/install) for making the HTTP requests.
* Wrap the API call with the BLoC pattern.
* Use Streams to display the users' list & the users' count.


Let's start by creating an App using the command below using Terminal.

```shell

flutter create http_for_flutter

```

Add the http package to the pubspec.yaml file

```yaml

dependencies:
  flutter:
    sdk: flutter
  http: ^0.12.2

```

Create the user.dart file below in the (lib\models) folder, we will create the User from the API's json response.

```dart

class User {
  final String name;
  final String email;
  final String symbol;
  final String phone;

  User.fromJson(Map<String, dynamic> json)
      : name = json['name'],
        email = json['email'],
        symbol = json['username'].toString().substring(0, 1),
        phone = json['phone'];
}


```

Create the users_service.dart file below in the (lib\services) folder. We will convert the API's response to a list of users.

```dart

import 'package:http/http.dart' as http;
import 'dart:convert' as convert;

import 'package:http_for_flutter/models/user.dart';

class UserService {
  static String _url = 'https://jsonplaceholder.typicode.com/users';
  static Future browse() async {
    List collection;
    List<User> _contacts;
    var response = await http.get(_url);
    if (response.statusCode == 200) {
      collection = convert.jsonDecode(response.body);
      _contacts = collection.map((json) => User.fromJson(json)).toList();
    } else {
      print('Request failed with status: ${response.statusCode}.');
    }

    return _contacts;
  }
}


```

Create the user_bloc.dart file below in the (lib\bloc) folder. UserBLoC will be the middleman between the source of data (UserService) and the widget. 
Note how we are listening to the usersList stream to update the userCounter stream


```dart

import 'dart:async';

import 'package:http_for_flutter/models/user.dart';
import 'package:http_for_flutter/services/users_service.dart';

class UserBLoC {
  Stream<List<User>> get usersList async* {
    yield await UserService.browse();
  }

  final StreamController<int> _userCounter = StreamController<int>();

  Stream<int> get userCounter => _userCounter.stream;

  UserBLoC() {
    usersList.listen((list) => _userCounter.add(list.length));
  }
}

```

We need to update the main.dart to use a StreamBuilder in the AppBar to display the number of users using the (userBLoC.userCounter) stream, and we will use another one in the body to display the list of users using (userBLoC.usersList) stream.

```dart

import 'package:flutter/material.dart';
import 'package:http_for_flutter/bloc/user_bloc.dart';
import 'package:http_for_flutter/models/user.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Users List',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Users List Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  UserBLoC userBLoC = new UserBLoC();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Users'),
        actions: [
          Chip(
            label: StreamBuilder<int>(
                stream: userBLoC.userCounter,
                builder: (context, snapshot) {
                  return Text(
                    (snapshot.data ?? 0).toString(),
                    style: TextStyle(
                        color: Colors.white, fontWeight: FontWeight.bold),
                  );
                }),
            backgroundColor: Colors.red,
          ),
          Padding(
            padding: EdgeInsets.only(right: 16),
          )
        ],
      ),
      body: StreamBuilder(
          stream: userBLoC.usersList,
          builder: (context, snapshot) {
            switch (snapshot.connectionState) {
              case ConnectionState.none:
              case ConnectionState.waiting:
              case ConnectionState.active:
                return Center(child: CircularProgressIndicator());
              case ConnectionState.done:
                if (snapshot.hasError)
                  return Text('There was an error : ${snapshot.error}');
                List<User> users = snapshot.data;

                return ListView.separated(
                  itemCount: users?.length ?? 0,
                  itemBuilder: (BuildContext context, int index) {
                    User _user = users[index];
                    return ListTile(
                      title: Text(_user.name),
                      subtitle: Text(_user.email),
                      leading: CircleAvatar(
                        child: Text(_user.symbol),
                      ),
                    );
                  },
                  separatorBuilder: (context, index) => Divider(),
                );
            }
          }),
    );
  }
}


```

Run the App and you will get the screen below

![Simulator Screen Shot - iPhone 12 Pro Max - 2021-01-27 at 13.40.56](https://i.imgur.com/mEjmUPm.png)


Check the code <a href="https://github.com/offlineprogrammer/http_for_flutter">here</a>

> Follow me on <a href="https://twitter.com/_Mo_Malaka_">Twitter</a> for more tips about #coding, #learning, #technology...etc.

> Check my Apps on <a href="https://bit.ly/3h05gQ7">Google Play</a>

> <span>Cover image <a href="https://unsplash.com/@mitchkmetz?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Mitchell Kmetz</a> on <a href="https://unsplash.com/s/photos/stream?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></span>