BLOC说明
bloc 是一个可预测的状态管理库,有助于实现 BLoC 设计模式。简单和轻便,高度可测试,适用于 Dart、Flutter 和 AngularDart。
简单使用
- 声明自定义bloc类,继承于Bloc, 然后添加相应的事件对象和状态的处理(通过emit把新的状态反馈出去),如下:
/// APP全局Bloc类
class AppGlobalBloc extends Bloc<_AppGlobalEvent, AppGlobalState> {
AppGlobalBloc(super.initialState) {
// 下面在注册相应的事件,并在事件接收后变更状态
on<_AppGlobalChangeThemeColorEvent>(
(event, emit) => emit(state.copyWith(themeColor: event.themeColor)));
on<_AppGlobalChangeUserNameEvent>(
(event, emit) => emit(state.copyWith(userName: event.userName)));
}
/// 变更主题色,就是添加一个变更主题色的事件
void changeThemeColor(MaterialColor themeColor) =>
add(_AppGlobalChangeThemeColorEvent(themeColor: themeColor));
/// 变更用户名,就是添加一个变更用户名的事件
void changeUserName(String? userName) =>
add(_AppGlobalChangeUserNameEvent(userName: userName));
}
/// 全局状态类
class AppGlobalState {
AppGlobalState({
this.themeColor = Colors.indigo,
this.userName = "酱酱紫",
});
/// 主题色
MaterialColor themeColor;
/// 用户名称
String userName;
AppGlobalState copyWith({MaterialColor? themeColor, String? userName}) =>
AppGlobalState()
..themeColor = themeColor ?? this.themeColor
..userName = userName ?? this.userName;
static const List<MaterialColor> themeColors = Colors.primaries;
}
abstract class _AppGlobalEvent {}
class _AppGlobalChangeThemeColorEvent extends _AppGlobalEvent {
_AppGlobalChangeThemeColorEvent({this.themeColor});
MaterialColor? themeColor;
}
class _AppGlobalChangeUserNameEvent extends _AppGlobalEvent {
_AppGlobalChangeUserNameEvent({this.userName});
String? userName;
}
- main.dart中处理的Application的主题变更监听
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(Application());
if (Platform.isAndroid) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle(statusBarColor: Colors.transparent));
}
}
class Application extends StatelessWidget {
Application({super.key});
final GoRouter _router = GoRouter(routes: [
GoRoute(
path: '/',
pageBuilder: (_, __) =>
const CupertinoPage(child: HomePage(title: "首页"))),
]);
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider(create: (_) => AppGlobalBloc(AppGlobalState())), //全局Bloc对象
],
child: BlocBuilder<AppGlobalBloc, AppGlobalState>(
builder: (_, state) => MaterialApp.router(
title: 'Flutter',
theme: ThemeData(primarySwatch: state.themeColor),
routerDelegate: _router.routerDelegate,
routeInformationParser: _router.routeInformationParser,
routeInformationProvider: _router.routeInformationProvider,
)));
}
}
-
在HomePage中处理主题色变更,先看一下UI效果图,如下
说明:通过点击上图中的颜色框,可以更改主题颜色,Bloc状态通知到位!
class HomePage extends StatefulWidget {
const HomePage({super.key, required this.title});
final String title;
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final HomePageBloc _bloc = HomePageBloc(HomePageState());
@override
void initState() {
_bloc.init();
super.initState();
}
@override
Widget build(BuildContext context) {
return WillPopScope(
child: Scaffold(
appBar: AppBar(centerTitle: true, title: Text(widget.title)),
body: BlocBuilder<HomePageBloc, HomePageState>(
bloc: _bloc,
builder: (ctx, state) => _buildContentView(state),
),
floatingActionButton: FloatingActionButton(
mini: true,
tooltip: 'Increment',
onPressed: _bloc.incrementCounter,
child: const Icon(Icons.add)),
floatingActionButtonLocation: FloatingActionButtonLocation.endTop,
),
onWillPop: () async => true);
}
Widget _buildContentView(HomePageState state) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Padding(
padding: EdgeInsets.only(top: 12, left: 12),
child: Text("主题颜色设置")),
Padding(
padding: const EdgeInsets.all(12),
child: Wrap(spacing: 12, runSpacing: 12, children: [
for (MaterialColor color in AppGlobalState.themeColors)
SizedBox(
width: 40,
height: 40,
child: InkWell(
onTap: () => context
.read<AppGlobalBloc>()
.changeThemeColor(color), //调用Bloc变更主题颜色的方法
child:
Container(width: 40, height: 40, color: color)))
])),
_buildItemView(title: "刘大能", address: "重庆渝中区大溪沟", phoneNumber: "132*****629"),
]);
}
Widget _buildItemView({String? title, String? address, String? phoneNumber}) {
return Card(
margin: const EdgeInsets.all(12.0),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
child: Padding(
padding: const EdgeInsets.all(12),
child: Row(
children: [
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text("${title ?? ""} ${phoneNumber ?? ""}",
style:
const TextStyle(fontSize: 16, color: Colors.indigo)),
const Divider(height: 8, color: Colors.transparent),
Text("地址:${address ?? ""}",
style: const TextStyle(color: Colors.black38))
])
],
)));
}
}
这里是Bloc的一个简单实用案例,希望对各位Bloc的学习者有所帮助。