Streams in, streams out…

How to listen to real-time data apart from StreamBuilder….? Hmmm…..

Begin…

Recently, a state management package called Provider was announced by Flutter team at Google I/O 2019.

How to use…

Add this dependency in your pubspec.yaml.

provider: ^2.0.0+1
Flutter Provider and Streams
Flutter Provider and Streams

Listen to data…

We had StreamBuilder in Flutter…

Hands down, best widget for listening real-time data…

This takes two arguments

  • A stream
  • A builder, that can convert the elements of the stream to widgets
StreamBuilder(
stream: //YOUR STREAM,
builder: (BuildContext context, AsyncSnapshot snapshot){
return //YOUR CHILD;
})

Now we also have StreamProvider……..:)

This comes from provider package.

StreamProvider<LocationModelNormal>.value(
initialData: LocationModelNormal.initialData(),
stream: locationStreamInstance.specificLocation(_secondWonder),
child: SecondStreamWidget(),
),
  1. In StreamProvider, we need to specify the type of object we are listening to…. 

In above case, LocationModelNormal (model class)…


LocationModelNormal class (below)….


class LocationModelNormal {
final String name;

final String url;

final GeoPoint coordinates;

final String videoURL;

LocationModelNormal({
this.name,
this.url,
this.coordinates,
this.videoURL,
});

factory LocationModelNormal.fromMap(Map<String, dynamic> data) {
return LocationModelNormal(
name: data['name'] ?? '',
url: data['url'] ?? '',
coordinates: data['location'] ?? null,
videoURL: data['link'] ?? '',
);
}

factory LocationModelNormal.initialData() {
return LocationModelNormal(
coordinates: null,
name: '',
videoURL: '',
url:'',
);
}
}

2. Next, we provide the initialData.

In our case, LocationModelNormal.initialData()….(See the snippet above)

3. Finally, we provide the child widget.

In our case, SecondStreamWidget()…

Pretty similar to StreamBuilder, right !!!!!!!!! 🙂


Access Data in Child…

Now that we have StreamProvider setup, we need to show the results in the child…

For accessing the data, (in your child)….

var data = Provider.of<LocationModelNormal>(context);

Here, we specified the result expected from our stream, using Provider.of<Type>(context)..

In our case, Type = LocationModelNormal

In action,

Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Text(‘${data.name}'),
),

where, data = the variable we specified above…

Listen to Network Changes…

Flutter Provider and Streams
Flutter Provider and Streams

When injecting many values in big applications, Provider can rapidly become pretty nested, thats why we have MultiProvider

MultiProvider(
  providers: [
    Provider<Foo>.value(value: foo),
    Provider<Bar>.value(value: bar),
    Provider<Baz>.value(value: baz),
  ],
  child: someWidget,
)

Use-Case…

In our example, we listen to the network changes, before fetching other streams…..

How to do,

  1. Install the connectivity dependency
  2. Wrap your MaterialApp with MultiProvider
return MultiProvider(
providers: [
StreamProvider<ConnectionStatus>.value(
stream:streamConnectivityService().connectivityController.stream,
),
],
child: MaterialApp(
home: Home(),
),
);

Here, the model class is ConnectionStatus

Now, your Home widget will get the changes in the network connectivity…You can render different UIs accordingly…

Values emitted are….

Wifi, offline or mobile data….

Widget build(BuildContext context) {
var network = Provider.of<ConnectionStatus>(context);
final _width = MediaQuery.of(context).size.width;
final _height = MediaQuery.of(context).size.height;

if (network == ConnectionStatus.wifi ||
network == ConnectionStatus.mobileData) {
return Container(
child: child,
);
}

return Container(
height: _height,
width: _width,
child: Text('YOU ARE OFFLINE'),
);
}

Src code : https://github.com/AseemWangoo/flutter_programs/blob/master/provider.zip

Valuable comments