本节目标
- 为什么要用 bloc
- bloc vs provider
- 学习路线推荐
- 安装 bloc vscode 插件
- 配置 bloc 依赖包
- 编写计算器示例
视频
代码
正文
为什么要用 bloc
-
状态管理(这是必须的)
-
三层分离
- 表现层(Presentation)
- 业务逻辑(Business Logic)
- 数据层(Data)
- 数据源/库(Repository)
- 数据提供者(Data Provider)
-
规范组内开发
-
方便的 测试、记录 用户行为
class SimpleBlocDelegate extends BlocDelegate {
@override
void onEvent(Bloc bloc, Object event) {
super.onEvent(bloc, event);
print('${bloc.runtimeType} $event');
// 所有的UI事件
// 可用 umeng 这样平台 进行跟踪
}
@override
void onError(Bloc bloc, Object error, StackTrace stacktrace) {
super.onError(bloc, error, stacktrace);
print('${bloc.runtimeType} $error');
// 所有发生的错误
// 用 sentry 记录错误
}
@override
void onTransition(Bloc bloc, Transition transition) {
super.onTransition(bloc, transition);
print(transition);
// 所有的 State 变化
}
}
bloc vs provider
-
bloc 是一种 mvvm 基于 事件、状态 驱动的
-
provider 是基于方法的
bloc 学习路线
-
Flutter Bloc 快速上手 -> Stream -> Cubit -> Bloc
-
理解基于 mvvm 组件化拆分
安装 bloc vscode 插件
bloc
创建项目
- pubspec.yaml
name: ducafecat_bloc_start_example
...
dependencies:
...
bloc: ^6.1.0
flutter_bloc: ^6.1.0
equatable: ^1.2.5
- 目录结构
counter 计算器业务下创建 bloc view 目录,这样就分离了
编写 bloc
- lib/counter/bloc/counter_bloc.dart
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';
part 'counter_event.dart';
part 'counter_state.dart';
class CounterBloc extends Bloc<CounterEvent, CounterState> {
CounterBloc() : super(CounterInitial(0));
int counterNum = 0;
@override
Stream<CounterState> mapEventToState(
CounterEvent event,
) async* {
if (event is CounterIncrement) {
yield* _mapIncrementEventToState(event);
} else if (event is CounterSubduction) {
yield* _mapSubductionEventToState(event);
}
}
Stream<CounterState> _mapIncrementEventToState(
CounterIncrement event) async* {
this.counterNum += 1;
yield CounterChange(this.counterNum);
}
Stream<CounterState> _mapSubductionEventToState(
CounterSubduction event) async* {
this.counterNum -= 1;
yield CounterChange(this.counterNum);
}
}
- lib/counter/bloc/counter_event.dart
part of 'counter_bloc.dart';
@immutable
abstract class CounterEvent extends Equatable {
@override
List<Object> get props => [];
}
class CounterIncrement extends CounterEvent {}
class CounterSubduction extends CounterEvent {}
- lib/counter/bloc/counter_state.dart
part of 'counter_bloc.dart';
@immutable
abstract class CounterState extends Equatable {
final int value;
const CounterState(this.value);
@override
List<Object> get props => [value];
}
class CounterInitial extends CounterState {
CounterInitial(int value) : super(value);
}
class CounterChange extends CounterState {
CounterChange(int value) : super(value);
}
编写 view
- lib/counter/view/page.dart
import 'package:ducafecat_bloc_start_example/counter/bloc/counter_bloc.dart';
import 'package:ducafecat_bloc_start_example/counter/view/view.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class CounterPage extends StatelessWidget {
const CounterPage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => CounterBloc(),
child: CounterView(),
);
}
}
- lib/counter/view/view.dart
import 'package:ducafecat_bloc_start_example/counter/bloc/counter_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class CounterView extends StatelessWidget {
const CounterView({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Counter')),
body: Center(
child: Column(
children: [
BlocBuilder<CounterBloc, CounterState>(
builder: (context, state) {
return Text('${state.value}');
},
),
RaisedButton(
child: Text('加法'),
onPressed: () {
BlocProvider.of<CounterBloc>(context).add(CounterIncrement());
},
),
RaisedButton(
child: Text('加法'),
onPressed: () {
BlocProvider.of<CounterBloc>(context).add(CounterSubduction());
},
)
],
),
),
);
}
}
替换主程序 widget
- lib/main.dart
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
...
home: CounterPage(), //MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
参考
- bloclibrary.dev/
- pub.flutter-io.cn/packages/bl…
- pub.flutter-io.cn/packages/fl…
- pub.flutter-io.cn/packages/eq…
- pub.flutter-io.cn/packages/pr…
© 猫哥