使用Flutter Files插件快速生成BLoC模板代码
VSCode 的 Flutter Files 插件是一个非常实用的工具,安装后在项目栏右击可以新建对应的模板代码。选择【new small pack bloc】,输入page名称(小写下划线风格如:wesin_test),就会自动生成一个完整的BLoC结构。
生成的文件结构
选择该功能后会生成一个wesin_test文件夹,包含以下文件:
- wesin_test_page.dart
- wesin_test_screen.dart
- wesin_test_bloc.dart
- wesin_test_event.dart
- wesin_test_state.dart
各文件功能解析
1. page文件
page文件定义了路由名称和页面主体结构:
dart
class RegisterPage extends StatefulWidget {
static const String routeName = '/register';
RegisterPage(this.phone, this.verifyCode);
final String verifyCode;
final String phone;
@override
_RegisterPageState createState() => _RegisterPageState();
}
class _RegisterPageState extends State<RegisterPage> {
final _registerBloc = RegisterBloc(RegisterState());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(LS.of(context, "register")),
),
body: BlocProvider(
create: (_) => _registerBloc,
child: RegisterScreen(widget.phone),
),
);
}
}
page作为主体页面,定义了route名称。在state的build方法中构建了BlocProvider
,为下级widget注册了一个RegisterBloc
。
2. screen文件
screen主要负责构建页面内容:
dart
class RegisterScreen extends StatelessWidget {
const RegisterScreen(
this.phone, {
Key? key,
}) : super(key: key);
final String phone;
@override
Widget build(BuildContext context) {
return BlocListener<RegisterBloc, RegisterState>(
listener: (ctx, state) {
if (state.status.isSubmissionInProgress) {
EasyLoading.show(
maskType: EasyLoadingMaskType.clear, dismissOnTap: false);
return;
}
if (state.status.isSubmissionFailure) {
EasyLoading.dismiss();
var message = LS.of(context, "register_error");
EasyLoading.showError('$message:${state.errMessage ?? ''}');
return;
}
if (state.status.isSubmissionSuccess) {
EasyLoading.dismiss();
showCupertinoDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Text(LS.of(context, "register_success")),
actions: [
TextButton(
onPressed: () {
Navigator.of(context)
.popUntil(ModalRoute.withName("/"));
},
child: Text(LS.of(context, "confirm")))
],
);
});
}
},
child: Align(
alignment: Alignment(0, -1),
child: Padding(
padding: const EdgeInsets.only(top: 31, left: 36, right: 36),
child: Column(children: [
_UsernameInput(),
_PasswordInput(),
_ConfirmPasswordInput(),
const SizedBox(
height: 20,
),
_RegisterButton()
]),
)));
}
}
BlocListener:监听状态消息,适合用于弹出加载页、错误信息等不需要重建子widget的场景。
BlocBuilder :包装需要更新的内容,建议在组装页面时尽量在涉及更新的地方使用,并考虑buildWhen
属性以优化性能。
3. bloc文件
bloc负责处理事件和状态变更:
dart
class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
RegisterBloc(RegisterState initialState) : super(initialState);
@override
Stream<RegisterState> mapEventToState(
RegisterEvent event,
) async* {
try {
yield* event.applyAsync(currentState: state, bloc: this);
} catch (_, stackTrace) {
developer.log('$_', name: 'RegisterBloc', error: _, stackTrace: stackTrace);
yield state;
}
}
}
4. event文件
将事件处理逻辑放在event文件中执行,代码更清晰,符合设计模式原则。
开发工具推荐
在iOS开发过程中,除了VSCode的Flutter插件外,appuploader也是一个非常实用的工具。它可以帮助开发者更高效地管理iOS应用的构建和上传流程,特别适合需要频繁测试和发布的开发场景。
appuploader提供了简洁的界面和自动化功能,可以大大减少手动操作的时间,让开发者能够更专注于代码编写和功能实现。与Flutter Files插件类似,它也是通过简化重复性工作来提高开发效率的优秀工具。