# How to Use Provider for State Management in Flutter || Part - 2

In Flutter, managing state efficiently is crucial for building responsive and dynamic applications. In the first part of this series, we explored the basics of using the **Provider** package for state management. In this second part, we will delve deeper into `FutureProvider` and `StreamProvider`, two powerful tools that help handle asynchronous data in Flutter apps. By understanding how to use these providers, you can ensure your app remains responsive and provides a seamless user experience. If you missed the first part, you can check it out [**here**.](https://blog.joflee.com/how-to-use-provider-for-state-management-in-flutter-part-1)

## What is FutureProvider?

In Flutter, `FutureProvider` is a part of the **Provider** package, which helps manage state in your app. Let me explain what it does:

1. **Purpose of**`FutureProvider`:
    
    * `FutureProvider` is used to provide a value that might not be ready when the widget tree is built. It ensures that a null value isn’t passed to any widgets.
        
    * The main use-case is to handle asynchronous operations (like fetching data from an API) and provide the result to widgets once the future is completed.
        
2. **How it works:**
    
    * You wrap your widget tree with a `FutureProvider`.
        
    * The `FutureProvider` takes a `Future` class (e.g., an API call) and updates the widgets depending on it when the future completes.
        
    * Until the future resolves, you can provide an initial value (e.g., a loading spinner) to avoid null errors.
        
3. **Example:**
    
    ```dart
    FutureProvider<String>(
      create: (_) => fetchDataFromApi(), // Your async operation
      initialData: 'Loading...', // Initial value
      child: MyWidget(),
    )
    ```
    

Remember, `FutureProvider` is particularly useful when dealing with asynchronous data in your Flutter app!

---

## How to use FutureProvider in a Flutter app?

In Flutter, `FutureProvider` from the **Provider** package is used to handle asynchronous operations and provide the result to widgets once the future completes. Here’s how you can use it:

1. **Exposing an Immutable Value:**
    
    * If you have an “immutable value” that needs to be asynchronously loaded (e.g., a config file), use `FutureProvider` like this:
        
        ```dart
        FutureProvider<MyConfig>(
          builder: (_) async {
            final json = await // Load JSON from somewhere (e.g., an API);
            return MyConfig.fromJson(json);
          },
        )
        ```
        
2. **Combining with Mutations:**
    
    * To convert a `Future` into something easier to manipulate, combine `FutureProvider` with a mutable object (like `ChangeNotifier`):
        
        ```dart
        ChangeNotifierProvider(
          builder: (_) => Foo(),
          child: Consumer<Foo>(
            builder: (_, foo, __) {
              return FutureProvider.value(
                value: foo.someFuture,
                child: ... // Your widget tree
              );
            },
          ),
        )
        ```
        
    * This allows you to handle updates when the future completes.
        

Remember, `FutureProvider` is particularly useful for managing asynchronous data in your Flutter app!

---

## **What is StreamProvider?**

In Flutter, **StreamProvider** is a state management solution that leverages the power of the Dart Stream API and the simplicity of Flutter’s Provider package. Here’s what you need to know:

1. **Purpose of StreamProvider:**
    
    * **Exposing a Stream**: StreamProvider is used to expose a stream and allows its descendants to access the latest value emitted by that stream.
        
    * **Listening to Changes**: It listens to the stream and automatically updates the widgets when new data arrives.
        
2. **How to Use StreamProvider:**
    
    * Wrap your widget tree with StreamProvider:
        
        ```dart
        StreamProvider<int>(
          create: (_) => myStream, // Your stream (e.g., from Firestore, WebSocket, etc.)
          initialData: 0, // Initial value
          child: MyWidget(),
        )
        ```
        
    * Replace `int` with the type of data your stream emits (e.g., `String`, `List<User>`, etc.).
        
3. **Difference Between StreamProvider and StreamBuilder:**
    
    * **StreamBuilder**: Rebuilds itself every time the stream updates. It’s a built-in Flutter widget.
        
    * **StreamProvider**: Combines `StreamBuilder` with `InheritedWidget`, allowing efficient data passing through the widget tree.
        

---

## How to use StreamProvider in a Flutter app?

In your Flutter app, **StreamProvider** is a powerful way to handle asynchronous data using streams. Let’s dive into how you can use it:

1. **Import the Necessary Packages:** First, make sure you have the `provider` package added to your `pubspec.yaml` file:
    
    ```yaml
    dependencies:
      flutter:
        sdk: flutter
      provider: ^6.1.2
    ```
    
2. **Create a StreamProvider:** Wrap your widget tree with `StreamProvider`. Specify the type of data your stream emits (e.g., `Stream<int>` or `Stream<List<User>>`):
    
    ```dart
    StreamProvider<int>(
      create: (_) => myStream, // Your stream (e.g., from Firestore, WebSocket, etc.)
      initialData: 0, // Initial value
      child: MyWidget(),
    )
    ```
    
3. **Access the Stream in Your Widgets:** Inside `MyWidget` or any descendant widget, use `context.watch` or `context.read` to access the stream:
    
    ```dart
    final myValue = context.watch<int>(); // Access the stream value
    ```
    
4. **Update UI When Stream Emits Data:** Whenever your stream emits new data, the widgets wrapped by `StreamProvider` will automatically rebuild with the updated value.
    

Remember, `StreamProvider` simplifies handling asynchronous data in your app!

---

## What is ValueListenableBuilder in flutter?

Certainly! The `ValueListenableBuilder` in Flutter is a handy widget that keeps its content in sync with a `ValueListenable`. Here’s how it works:

1. **What is**`ValueListenableBuilder`?
    
    * `ValueListenableBuilder` is a widget that listens to changes in a `ValueListenable` and automatically rebuilds its content when the value changes.
        
    * You provide a `ValueListenable<T>` and a builder function that creates widgets based on the current value of the `ValueListenable`.
        
    * When the value changes, the builder function is called with the updated value, allowing you to update your UI accordingly.
        
2. **Usage Example:**
    
    ```dart
    ValueListenableBuilder<int>(
      valueListenable: myValueListenable, // Your ValueListenable instance
      builder: (BuildContext context, int value, Widget? child) {
        // Build your UI based on the current value
        return Text('Count: $value');
      },
    )
    ```
    
3. **Performance Optimisation:**
    
    * If your builder function contains a subtree that doesn’t depend on the `ValueListenable` value, you can pass a pre-built subtree as the `child` parameter.
        
    * This pre-built child is optional but can significantly improve performance in some cases.
        
4. **Other Similar Widgets:**
    
    * `AnimatedBuilder`: Rebuilds based on a `Listenable` without passing back a specific value.
        
    * `NotificationListener`: Rebuilds based on notifications from descendant widgets.
        
    * `StreamBuilder`: For more advanced use cases involving streams.
        
    * `TweenAnimationBuilder`: Animates values based on a `Tween`.
        

Remember to replace `myValueListenable` with your actual `ValueListenable` instance.

---

## How to create your own ValueNotifier in Flutter?

Certainly! Creating your own `ValueNotifier` in Flutter is straightforward. It’s a simple class that extends `ChangeNotifier` and provides a way to store a single value that can be listened to and updated reactively. Let’s walk through an example:

```dart
import 'package:flutter/material.dart';

class CounterModel extends ValueNotifier<int> {
  CounterModel(int value) : super(value);

  void increment() => value++;
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counter = CounterModel(0);

    return MaterialApp(
      title: 'ValueNotifier Demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text('ValueNotifier Demo'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text('You have pushed the button this many times:'),
              ValueListenableBuilder(
                valueListenable: counter,
                builder: (BuildContext context, int value, Widget? child) {
                  return Text(
                    '$value',
                    style: Theme.of(context).textTheme.headline4,
                  );
                },
              ),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            counter.increment();
          },
          tooltip: 'Increment',
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}
```

In this example:

1. We define a `CounterModel` class that extends `ValueNotifier<int>`.
    
2. The `increment()` method updates the counter value.
    
3. We create an instance of `CounterModel` and pass it to `ValueListenableBuilder`, which listens to changes in the counter value and rebuilds the widget tree when the value changes.
    

Using `ValueNotifier` is that simple! It's a great choice for small to medium-sized projects where you don't need the complexity of other state management solution. keep in mind that for larger or more complex projects, other state management solutions like Riverpod, Provider, Bloc, or Redux might be more suitable.

---

> In this article, we explored `FutureProvider` and `StreamProvider` in Flutter. These tools help manage asynchronous data, ensuring your app remains responsive and dynamic. By using these providers, you can efficiently handle state management in your Flutter applications.

%%[linkedinwidget]
