Created
August 11, 2022 04:16
-
-
Save HelloCore/2093e75585d07bcca68a00f65c4bc5a7 to your computer and use it in GitHub Desktop.
GlobalContext2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This code is distributed under the MIT License. | |
// Copyright (c) 2018 Felix Angelov. | |
// You can find the original at https://github.com/felangel/bloc. | |
import 'package:flutter/material.dart'; | |
import 'package:flutter_bloc/flutter_bloc.dart'; | |
void main() { | |
BlocOverrides.runZoned( | |
() => runApp(const App()), | |
blocObserver: AppBlocObserver(), | |
); | |
} | |
/// Custom [BlocObserver] that observes all bloc and cubit state changes. | |
class AppBlocObserver extends BlocObserver { | |
@override | |
void onChange(BlocBase bloc, Change change) { | |
super.onChange(bloc, change); | |
if (bloc is Cubit) print(change); | |
} | |
@override | |
void onTransition(Bloc bloc, Transition transition) { | |
super.onTransition(bloc, transition); | |
print(transition); | |
} | |
} | |
/// {@template app} | |
/// A [StatelessWidget] that: | |
/// * uses [bloc](https://pub.dev/packages/bloc) and | |
/// [flutter_bloc](https://pub.dev/packages/flutter_bloc) | |
/// to manage the state of a counter and the app theme. | |
/// {@endtemplate} | |
class App extends StatelessWidget { | |
/// {@macro app} | |
const App({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return BlocProvider( | |
create: (_) => ThemeCubit(), | |
child: const AppView(), | |
); | |
} | |
} | |
/// {@template app_view} | |
/// A [StatelessWidget] that: | |
/// * reacts to state changes in the [ThemeCubit] | |
/// and updates the theme of the [MaterialApp]. | |
/// * renders the [CounterPage]. | |
/// {@endtemplate} | |
class AppView extends StatelessWidget { | |
/// {@macro app_view} | |
const AppView({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return BlocBuilder<ThemeCubit, ThemeData>( | |
builder: (_, theme) { | |
return MaterialApp( | |
theme: theme, | |
home: const CounterPage(), | |
); | |
}, | |
); | |
} | |
} | |
/// {@template counter_page} | |
/// A [StatelessWidget] that: | |
/// * provides a [CounterBloc] to the [CounterView]. | |
/// {@endtemplate} | |
class CounterPage extends StatelessWidget { | |
/// {@macro counter_page} | |
const CounterPage({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
globalContext = context; | |
return BlocProvider( | |
create: (_) => CounterBloc(), | |
child: const CounterView(), | |
); | |
} | |
} | |
late BuildContext globalContext; | |
/// {@template counter_view} | |
/// A [StatelessWidget] that: | |
/// * demonstrates how to consume and interact with a [CounterBloc]. | |
/// {@endtemplate} | |
class CounterView extends StatelessWidget { | |
/// {@macro counter_view} | |
const CounterView({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: const Text('Counter')), | |
body: Center( | |
child: Column(children: [ | |
BlocBuilder<CounterBloc, int>( | |
builder: (context, count) { | |
return Text('$count', style: Theme.of(context).textTheme.headline1); | |
}, | |
), | |
BlocSelector<CounterBloc, int, int>( | |
selector: (count) { | |
return count; | |
}, | |
builder: (context, count) { | |
final brightness = context.watch<ThemeCubit>().state.brightness; | |
return Text('$count LocalContext $brightness'); | |
}, | |
), | |
BlocSelector<CounterBloc, int, int>( | |
selector: (count) { | |
return count; | |
}, | |
builder: (context, count) { | |
final brightness = globalContext.watch<ThemeCubit>().state.brightness; | |
return Text('$count GlobalContext $brightness'); | |
}, | |
), | |
],), | |
), | |
floatingActionButton: Column( | |
crossAxisAlignment: CrossAxisAlignment.end, | |
mainAxisAlignment: MainAxisAlignment.end, | |
children: <Widget>[ | |
FloatingActionButton( | |
child: const Icon(Icons.add), | |
onPressed: () => context.read<CounterBloc>().add(Increment()), | |
), | |
const SizedBox(height: 4), | |
FloatingActionButton( | |
child: const Icon(Icons.remove), | |
onPressed: () => context.read<CounterBloc>().add(Decrement()), | |
), | |
const SizedBox(height: 4), | |
FloatingActionButton( | |
child: const Icon(Icons.brightness_6), | |
onPressed: () => context.read<ThemeCubit>().toggleTheme(), | |
), | |
], | |
), | |
); | |
} | |
} | |
/// Event being processed by [CounterBloc]. | |
abstract class CounterEvent {} | |
/// Notifies bloc to increment state. | |
class Increment extends CounterEvent {} | |
/// Notifies bloc to decrement state. | |
class Decrement extends CounterEvent {} | |
/// {@template counter_bloc} | |
/// A simple [Bloc] that manages an `int` as its state. | |
/// {@endtemplate} | |
class CounterBloc extends Bloc<CounterEvent, int> { | |
/// {@macro counter_bloc} | |
CounterBloc() : super(0) { | |
on<Increment>((event, emit) => emit(state + 1)); | |
on<Decrement>((event, emit) => emit(state - 1)); | |
} | |
} | |
/// {@template brightness_cubit} | |
/// A simple [Cubit] that manages the [ThemeData] as its state. | |
/// {@endtemplate} | |
class ThemeCubit extends Cubit<ThemeData> { | |
/// {@macro brightness_cubit} | |
ThemeCubit() : super(_lightTheme); | |
static final _lightTheme = ThemeData( | |
floatingActionButtonTheme: const FloatingActionButtonThemeData( | |
foregroundColor: Colors.white, | |
), | |
brightness: Brightness.light, | |
); | |
static final _darkTheme = ThemeData( | |
floatingActionButtonTheme: const FloatingActionButtonThemeData( | |
foregroundColor: Colors.black, | |
), | |
brightness: Brightness.dark, | |
); | |
/// Toggles the current brightness between light and dark. | |
void toggleTheme() { | |
emit(state.brightness == Brightness.dark ? _lightTheme : _darkTheme); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment