#100DaysOfCodeChallenge - Crop Management Information System - Day 10
Tags: 100daysofcode, flutter, dart, programming
Published: 2021-07-05 03:51:24

## Recap
On [Day 9](https://dev.to/curtlycritchlow/100daysofcodechallenge-crop-management-information-system-day-9-27dp) we access the device camera and stored the photo in cloud storage.

## Overview

In this post, we will discuss retrieving real time data from cloud firestore and displaying it to the user.

## Going Deeper

Retrieval and display of data from cloud firestore are divided into three (3) main parts. This division is done for readability and maintainability purposes.

### getAllFarmers method

```Dart
class FarmerService {
  final farmerRef =
      FirebaseFirestore.instance.collection('farmers').withConverter(
            fromFirestore: (snapshot, _) =>
                FarmerServiceModel.fromJson(snapshot.data()!),
            toFirestore: (farmerModel, _) => farmerModel.toJson(),
          );


  Stream<QuerySnapshot<FarmerServiceModel>> getAllFarmers() {
    return farmerRef.snapshots();
  }
}
```
The `getAllFarmers` method  returns a `Stream<QuerySnapshot<FarmerServiceModel>>` to `AllFarmerCommand().run()`

### AllFarmerCommand().run()

```Dart
class AllFarmerCommand extends BaseCommand {
  AllFarmerCommand(BuildContext c) : super(c);

  Stream<QuerySnapshot<FarmerServiceModel>> run() {
    farmerModel.farmers = farmerService.getAllFarmers();
    return farmerModel.farmers;
  }
}
```
This method calls `farmerService.getAllFarmers();`, assigns the returned stream to FarmerModel.farmers and to the method the `_AllFarmerScreenController()`

### AllFarmerScreen

```Dart
class AllFarmerScreen extends StatefulWidget {
  static String routeName = 'AllFarmerScreen';
  const AllFarmerScreen({
    Key? key,
  }) : super(key: key);

  @override
  _AllFarmerScreenController createState() => _AllFarmerScreenController();
}
```
This widget is the All Farmers Screen. It is comprised of a controller and layout widget. This widget is responsible for the screen logic and layout respectively.

#### AllFarmerScreenController
```Dart
class _AllFarmerScreenController extends State<AllFarmerScreen> {
  late Stream<QuerySnapshot<FarmerServiceModel>> stream;
  @override
  Widget build(BuildContext context) => _AllFarmerScreenView(this);

  @override
  void initState() {
    super.initState();
    stream = AllFarmerCommand(context).run();

    // stream = Provider.of<FarmerModel>(context, listen: false).farmers;
  }
}
```
`Stream<QuerySnapshot<FarmerServiceModel>>` from `farmerService.getAllFarmers();` is stored in a variable called stream when `iniState()` is called by flutter.

#### AllFarmerScreenView

```Dart
class _AllFarmerScreenView
    extends WidgetView<AllFarmerScreen, _AllFarmerScreenController> {
  final state;
  const _AllFarmerScreenView(this.state) : super(state);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('All Farmers'),
      ),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 24.0),
            child: Center(
              child: Text(
                'Farmer Register',
                style: TextStyles.title.bold,
              ),
            ),
          ),
          Expanded(
            child: StreamBuilder<QuerySnapshot<FarmerServiceModel>>(
              stream: state.stream,
              builder: (context, snapshot) {
                if (!snapshot.hasData) {
                  return Center(
                      child: SpinKitDoubleBounce(
                    color: Colours.accentColor(context),
                  ));
                } else if (snapshot.hasError) {
                  SnackBars.errorSnackBar(
                      content: 'Something went wrong', context: context);
                  print('something went wrong');
                  return Text('Something went wrong');
                } else if (snapshot.connectionState ==
                    ConnectionState.waiting) {
                  return Text("Loading");
                } else
                  return ListView(
                    children: snapshot.data!.docs
                        .map((DocumentSnapshot<FarmerServiceModel> document) {
                      FarmerServiceModel farmer = document.data()!;
                      return FarmerIdentificationCard(
                        farmer: farmer,
                      );
                    }).toList(),
                  );
              },
            ),
          )
        ],
      ),
    );
  }
}
```

This widget is responsible for the layout of the `AllFarmerScreen`. We will discuss the stream builder part of the code.

```Dart
Expanded(
            child: StreamBuilder<QuerySnapshot<FarmerServiceModel>>(
              stream: state.stream,
              builder: (context, snapshot) {
                if (!snapshot.hasData) {
                  return Center(
                      child: SpinKitDoubleBounce(
                    color: Colours.accentColor(context),
                  ));
                } else if (snapshot.hasError) {

                  SnackBars.errorSnackBar(
                      content: 'Something went wrong', context: context);
                  print('something went wrong');
                  return Text('Something went wrong');
                } else if (snapshot.connectionState ==
                    ConnectionState.waiting) {
                  return Text("Loading");
                } else
                  return ListView(
                    children: snapshot.data!.docs
                        .map((DocumentSnapshot<FarmerServiceModel> document) {
                      FarmerServiceModel farmer = document.data()!;
                      return FarmerIdentificationCard(
                        farmer: farmer,
                      );
                    }).toList(),
                  );
              },
            ),
          )
```
Stream builder will receive updates every time a document is added, deleted or edited in the farmers collection.

Before we extract any documents from the snapshot, we do three (3) main checks. First, we check for data in the snapshot, secondly, we check for errors and lastly we check for the connection state. Once we pass the checks, we return a listview.

Within the listview, each document from the snapshot is converted to a `FarmerIdentificationCard()` widget. Screenshot of the Identification card is shown below.

![Preview of Farmer Profile picture in cloud storage](https://drive.google.com/uc?id=1-jTFUIpjSUpjO9i-ORaGd1vXIktcffUW)

## Wrap Up

In this post, we discussed how to retrieve data from a cloud firestore collection as a `Stream<QuerySnapshot`. We then used the snapshot to create a Farmer Identification Card widget for each document in the snapshot.


## Connect with me

Thank you for reading my post. Feel free to subscribe below to join me on the #100DaysOfCodeChallenge or connect with me on [LinkedIn](https://www.linkedin.com/in/curtlycritchlow/) and [Twitter](https://twitter.com/CritchlowCurtly). You can also [buy me a book](https://www.buymeacoffee.com/curtlycritchlow) to show your support.