Skip to content

Instantly share code, notes, and snippets.

@wingkit-leung
Last active February 15, 2022 17:07
Show Gist options
  • Save wingkit-leung/f203435e62adbcc3ce95da5277203533 to your computer and use it in GitHub Desktop.
Save wingkit-leung/f203435e62adbcc3ce95da5277203533 to your computer and use it in GitHub Desktop.
Flutter Example of using StateNotifierProvider, FutureBuilder vs FutureProvider and StreamBuilder vs StreamProvider
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() =>
runApp(const ProviderScope(child: MaterialApp(home: HomePage())));
Future<int> calculateSquare(int num) async {
await Future.delayed(const Duration(seconds: 2));
return num * num;
}
Stream<int> stopwatch() async* {
int counter = 0;
while (true) {
await Future.delayed(const Duration(seconds: 1));
yield counter++;
}
}
abstract class ProgressState {
const ProgressState();
}
class InitialState extends ProgressState {
const InitialState();
}
class LoadingState extends ProgressState {
const LoadingState();
}
class SuccessState extends ProgressState {
const SuccessState(this.value);
final int value;
}
class CounterStateNotifier extends StateNotifier<ProgressState> {
CounterStateNotifier() : super(const InitialState());
void start() {
if (state is InitialState) {
state = const LoadingState();
final stream = stopwatch();
stream.listen((value) {
state = SuccessState(value);
});
}
}
}
class SquareStateNotifier extends StateNotifier<ProgressState> {
SquareStateNotifier() : super(const InitialState());
Future<void> start() async {
if (state is InitialState) {
state = const LoadingState();
final result = await calculateSquare(10);
state = SuccessState(result);
}
}
}
final futureCalculateProvider = FutureProvider<int>((ref) {
return calculateSquare(10);
});
final squareStateNotifier =
StateNotifierProvider<SquareStateNotifier, ProgressState>((ref) {
final p = SquareStateNotifier();
p.start();
return p;
});
final streamCounterProvider = StreamProvider<int>((ref) {
return stopwatch();
});
final counterStateNotifier =
StateNotifierProvider<CounterStateNotifier, ProgressState>((ref) {
final p = CounterStateNotifier();
p.start();
return p;
});
Widget buildFutureBuilder() {
return Center(
child: FutureBuilder<int>(
future: calculateSquare(10),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Text(
"Square = ${snapshot.data}",
style:
DefaultTextStyle.of(context).style.apply(fontSizeFactor: 1.5),
);
}
return const CircularProgressIndicator();
},
),
);
}
Widget buildFutureConsumer() {
return Consumer(builder: (context, ref, _) {
final result = ref.watch(futureCalculateProvider);
return result.when(
loading: () => const CircularProgressIndicator(),
error: (err, stack) => Text('Error: $err'),
data: (snapshot) {
return Text(
"Square = $snapshot",
style: DefaultTextStyle.of(context).style.apply(fontSizeFactor: 1.5),
);
},
);
});
}
buildStateNotifierConsumerForFuture() {
return Consumer(builder: (context, ref, _) {
final state = ref.watch(squareStateNotifier);
//loading
if (state is LoadingState || state is InitialState) {
return const CircularProgressIndicator();
} else if (state is SuccessState) {
return Text(
"Square = ${state.value}",
style: DefaultTextStyle.of(context).style.apply(fontSizeFactor: 1.5),
);
}
return const Text('Unknown state');
});
}
Widget buildStreamBuilder() {
return Center(
child: StreamBuilder<int>(
stream: stopwatch(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
return Text(
"Stopwatch = ${snapshot.data}",
style:
DefaultTextStyle.of(context).style.apply(fontSizeFactor: 1.5),
);
}
return const CircularProgressIndicator();
},
),
);
}
buildStreamConsumer() {
return Consumer(builder: (context, ref, _) {
final result = ref.watch(streamCounterProvider);
return result.when(
loading: () => const CircularProgressIndicator(),
error: (err, stack) => Text('Error: $err'),
data: (snapshot) {
return Text(
"Stopwatch = $snapshot",
style: DefaultTextStyle.of(context).style.apply(fontSizeFactor: 1.5),
);
},
);
});
}
buildStateNotifierConsumerForStream() {
return Consumer(builder: (context, ref, _) {
final state = ref.watch(counterStateNotifier);
//loading
if (state is LoadingState || state is InitialState) {
return const CircularProgressIndicator();
} else if (state is SuccessState) {
return Text(
"Stopwatch = ${state.value}",
style: DefaultTextStyle.of(context).style.apply(fontSizeFactor: 1.5),
);
}
return const Text('Unknown state');
});
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Providers Example'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('FutureBuilder'),
buildFutureBuilder(),
const SizedBox(height: 10),
const Text('FutureProvider'),
buildFutureConsumer(),
const SizedBox(height: 10),
const Text('StateNotifierProvider (Future)'),
buildStateNotifierConsumerForFuture(),
const Divider(),
const Text('StreamBuilder'),
buildStreamBuilder(),
const SizedBox(height: 10),
const Text('StreamProvider'),
buildStreamConsumer(),
const SizedBox(height: 10),
const Text('StateNotifierProvider (Stream)'),
buildStateNotifierConsumerForStream(),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => const AnotherPage()));
},
child: const Icon(Icons.play_arrow_rounded),
),
);
}
}
class AnotherPage extends StatelessWidget {
const AnotherPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Another Page'),
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
const Text('Stream shared across pages?'),
const SizedBox(height: 80),
const Text('StreamBuilder ❌'),
buildStreamBuilder(),
const SizedBox(height: 30),
const Divider(),
const Text('StreamProvider ✅'),
buildStreamConsumer(),
const SizedBox(height: 30),
const Divider(),
const Text('StateNotifierProvider ✅'),
buildStateNotifierConsumerForStream(),
],
),
),
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment