# Flutter Riverpod Tutorial Part 2: Asynchronous Providers (FutureProvider and StreamProvider)

Part-1 Link : [https://harishkunchala.com/flutter-riverpod-tutorial-part-1-provider-and-stateprovider-statenotifierprovider-changenotifierprovider](https://harishkunchala.com/flutter-riverpod-tutorial-part-1-provider-and-stateprovider-statenotifierprovider-changenotifierprovider)

## FutureProvider

1. `FutureProvider` allows us to work with Futures in our Flutter Application
    
2. It automatically handles the lifecycle of asynchronous operation.
    
3. So it provides us with a way to react to the different states of the future: loading, error and data.
    

### Step 1: Add `http` to our `pubspec.yaml`

We are going to look at an actual networking example by showing either a single user or list of users from [JsonPlaceHolder Users API](https://jsonplaceholder.typicode.com/users). So let's add `http` into our pubspec.yaml

```bash
flutter pub add http
```

### Step 2: Create a FutureProvider for Fetching Data

First, we need to set up the `FutureProvider`. We will create a function that fetches data from the JSON Placeholder Users API and returns a list of users:

```dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:http/http.dart' as http;
import 'dart:convert'; // Required for jsonDecode

final usersProvider = FutureProvider<List<dynamic>>((ref) async {
  final url = Uri.parse('https://jsonplaceholder.typicode.com/users');
  final response = await http.get(url);

  if (response.statusCode == 200) {
    return jsonDecode(response.body);
  } else {
    throw Exception('Failed to load users');
  }
});
```

### Step 3: Building the UI to Display Data

Now, let's create the UI part where we use `usersProvider` to display the list of users or handle loading and error states:

```dart
class UsersScreen extends ConsumerWidget {
  const UsersScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final usersAsyncValue = ref.watch(usersProvider);
    return Scaffold(
      appBar: AppBar(
        title: const Text('Users'),
      ),
      body: usersAsyncValue.when(
        loading: () => const Center(child: CircularProgressIndicator()),
        error: (error, stackTrace) => Center(child: Text('Error: $error')),
        data: (users) => ListView.builder(
          itemCount: users.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text(users[index]['name']),
              subtitle: Text(users[index]['email']),
            );
          },
        )
      ),
    );
  }
```

If we look closely in the above example:

`usersAsyncValue.when()` handles the three states:

* `loading`: Displays a circular progress indicator.
    
* `error`: Shows an error message.
    
* `data`: Builds a list of users using a `ListView.builder`.
    

### Step 4: Run Our App

This is our current output:

![Future Provider](https://media0.giphy.com/media/v1.Y2lkPTc5MGI3NjExcHpwZWZxdjNpNTR2czN5Zmp6cGk0ZXdhODVlam00NjNwNWRrdHRnNCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/i4QAVvch9NzlwTEER4/giphy.gif align="center")

As always you can find the source code here: [https://github.com/khkred/flutter\_stack/tree/future\_provider](https://github.com/khkred/flutter_stack/tree/future_provider)

## StreamProvider

### Step 1: Create a StreamProvider

First, define a `StreamProvider` that sets up a stream. We'll use Dart's `Stream.periodic` to create a simple stream that emits an incrementing integer every second:

```dart

final counterStreamProvider = StreamProvider<int>((ref) {
  return Stream.periodic(const Duration(seconds: 1), (count) =>  count +1);
});
```

This provider creates a stream that emits an incrementing count every second, starting from 1.

### Step 2: Building the UI to Display our Stream Data

We will use a `ConsumerWidget` to consume the `counterStreamProvider` and update the UI every time a new value is emitted by the stream:

```dart

class CounterStreamScreen extends ConsumerWidget {
  const CounterStreamScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final counterAsyncValue = ref.watch(counterStreamProvider);
    return Scaffold(
      appBar: AppBar(
        title: const Text('Counter Stream'),
      ),
      body: Center(
        child: counterAsyncValue.when(
          data: (count) => Text('Current Count: $count', style: const TextStyle(fontSize: 24)),
          loading: () => const CircularProgressIndicator(),
          error: (error, stackTrace) => Text('Error: $error'),
        ),
      ),
    );
  }
}
```

In the above example:

* `counterAsyncValue.when()` handles the different states:
    
    * `loading`: Shows a circular progress indicator before the first value is emitted.
        
    * `error`: Displays an error message if there's an issue with the stream.
        
    * `data`: Updates the displayed count each time a new value is emitted from the stream.
        

### Step 3: Run our App

Here's our Counter Stream Screen:

![Counter Stream Screen](https://media2.giphy.com/media/v1.Y2lkPTc5MGI3NjExemczbDRjODBmbm9tcHM2d3pxYXVrMnQ4bXlicnRnZmJyMmtyN2g3dCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/RSnjrpZe3jyrpCaYEI/giphy.gif align="center")

And as always you can find the source code here: [https://github.com/khkred/flutter\_stack/tree/stream\_provider](https://github.com/khkred/flutter_stack/tree/stream_provider)

If you like to learn more about Flutter. Keep following my posts.
