Flutter Riverpod 2.0 Stream Provider brought an easy and powerful feature for continuous update of your app UI. This is supposed to be better version of StreamBuilder and make firebase data source or web socket data source easy reading updating the UI.
See how to do that
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'stream_screen_controller.g.dart';
@riverpod
class StreamScreenController extends _$StreamScreenController {
@override
Stream<String> build() async* {
for (var i = 0; i < 10; i++) {
final response = await http
.get(Uri.parse('https://random-word-api.herokuapp.com/word'));
if (response.statusCode == 200) {
final jsonResponse = jsonDecode(response.body);
final output = jsonResponse[0] as String;
yield output;
}
}
}
}
Here the build method, returns Stream<String>, it means we will continuously send some data and the data type would be String. So we say the return type is Stream<String>.
Stream means continuous data source. Since we have continuous data source, we need to make our build method async* as well. This means the current function is the data source and it will yield data. Here yield is special key word of Dart language.
Yield itself in pure English means, giving.
Our UI code
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:generate_riverpod/screens/stream_screen/provider/stream_screen_controller.dart';
import 'package:generate_riverpod/widgets/app_scaffold.dart';
class StreamScreen extends ConsumerWidget {
const StreamScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final state = ref.watch(streamScreenControllerProvider);
return Scaffold(
backgroundColor: Colors.grey,
// color: Colors.yellow,
// title: const Text('Stream Provider Sample'),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
state.when(
data: (data) => Text(
data,
style: const TextStyle(
fontSize: 40,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
error: (error, stackTrace) => Text(
error.toString(),
style: const TextStyle(
fontSize: 40,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
loading: () => const CircularProgressIndicator(),
),
],
),
),
);
}
}
Since we are a Stream data type, so we can access to when() function from given Providers of Riverpod. Once our data arrives, we can update our UI auto. Riverpod Stream Provider can auto detect each new data and update the UI.
Since our Stream Provider is assigned to a variable name state, we can access the data using state.when().
And when() function has other three properties like data
, error
and loading
. But these three are same AsnycNotifier and Future Provider.
And main.dart file
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({
super.key,
});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const StreamScreen(),
);
}
}