Skip to content

Instantly share code, notes, and snippets.

@Lootwig
Created December 8, 2021 17:09
Show Gist options
  • Save Lootwig/c31f3a2a6e1f8b8c54be802fb47ae669 to your computer and use it in GitHub Desktop.
Save Lootwig/c31f3a2a6e1f8b8c54be802fb47ae669 to your computer and use it in GitHub Desktop.
bloc_maybe_statechange
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Builder(builder: (context) {
return BlocProvider(
create: (context) {
return DataBloc(() {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Bloc has no new data :(')),
);
});
},
child: const FirstScreen(),
);
}),
);
}
}
class FirstScreen extends StatefulWidget {
const FirstScreen({
Key? key,
}) : super(key: key);
@override
State<FirstScreen> createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen> {
bool _loading = false;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: _loading
? null
: () async {
setState(() => _loading = true);
final bloc = context.read<DataBloc>();
final stateUpdate = bloc.stream.first;
bloc.add(
const DataEvent()); // this will only cause a state change every second time
final newState = await stateUpdate;
setState(() => _loading = false);
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => SecondScreen(data: newState.data),
),
);
},
child: const Text('Go to second screen'),
),
),
);
}
}
class SecondScreen extends StatelessWidget {
final List<int> data;
const SecondScreen({Key? key, required this.data}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: Text('New data is: $data. Now go back and try again.'),
),
);
}
}
class DataBloc extends Bloc<DataEvent, DataState> {
VoidCallback onNoNewData;
bool _hasNewData = true;
int newData = 1;
DataBloc(this.onNoNewData) : super(const DataInitial()) {
on<DataEvent>((event, emit) async {
if (_hasNewData) {
await Future.delayed(
const Duration(seconds: 2),
() => emit(DataState([newData++])),
);
} else {
onNoNewData();
}
_hasNewData = !_hasNewData;
});
}
}
class DataEvent {
const DataEvent();
}
class DataState /*extends Equatable*/ {
final List<int> data;
const DataState(this.data);
@override
bool operator ==(Object other) {
return other is DataState && other.data.every(data.contains);
}
}
class DataInitial extends DataState {
const DataInitial() : super(const []);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment