我们用简单的计数器,学习怎么使用Cubit来存取状态。
Dependency
pubspec.yaml
dependencies: flutter: sdk: flutter bloc: ^8.1.0 flutter_bloc: ^8.1.1
Counter Cubit
CounterCubit 用来储存 int 状态,所以继承于 Cubit<int>
,emit 是用来更改现在有状态。
lib/counter/cubit/counter_cubit.dart:
class CounterCubit extends Cubit<int> {CounterCubit(): super(0);void increment() => emit(state + 1);void decrement() => emit(state -1);}
Counter View
CounterView 用来呈现计数器的画面,用 BlocBuilder 来呼叫 CounterCubit 的方法与存取它的状态值。当 state 有变化的时候,BlocBuilder 就会帮我们重绘画面,不用再需要setState() 来重绘。
context.read() 可以用来呼叫 CounterCubit 的方法。
lib/counter/view/counter_view.dart:
class CounterView extends StatelessWidget { const CounterView({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final textTheme = Theme.of(context).textTheme; return Scaffold( appBar: AppBar( title: const Text('Counter'), centerTitle: true, ), body: Center( child: BlocBuilder<CounterCubit, int>(builder: (context, state) { return Text('\$state', style: textTheme.headline2); }), ), floatingActionButton: Column( mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end, children: [ FloatingActionButton( key: const Key("counterView_increment_floatingActionButton"), child: const Icon(Icons.add), onPressed: () => context.read<CounterCubit>().increment(), ), const SizedBox( height: 8, ), FloatingActionButton( key: const Key("counterView_decrement_floatingActionButton"), child: const Icon(Icons.remove), onPressed: () => context.read<CounterCubit>().decrement(), ) ], ), ); }}
输入 stl+enter,可以快速产生一个继承于 StatelessWidget 的类别。
Export
可以用一个同名的目录档案,可以用来整理 import library,让程式上面的 import 档案能够统一管理。
lib/counter/counter.dart:
export 'cubit/counter_cubit.dart';
Counter Page
CounterPage 是将 CounterCubit 实体化,然后提供给 CounterView。
lib/counter/view/counter_page.dart:
class CounterPage extends StatelessWidget { const CounterPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return BlocProvider( create: (_) => CounterCubit(), child: const CounterView()); }}
App
lib/app.dart
class CounterApp extends MaterialApp { const CounterApp({super.key}) : super(home: const CounterPage());}
BlocObserver
可以用 CounterObserver 继承 BlocObserver 来监控应用程式里,所有的状态。
lib/counter_observer
class CounterObserver extends BlocObserver { @override void onChange(BlocBase bloc, Change change) { super.onChange(bloc, change); print('${bloc.runtimeType} $change'); }}
lib/main.dart
void main() {Bloc.observer = CounterObserver(); runApp(const CounterApp());}
Summary
计数器的程式架构将实作层从业务逻辑层分开来,把业务逻辑写在 CounterCubit 裏面,CounterView 只要负责通知 CounterCubit。CounterCubit 也只要负责将新状态回传。