面试题答案
一键面试1. 传统StatefulWidget状态管理与响应式编程结合方式
- 使用Stream:
- 在
StatefulWidget
的State
类中,可以创建一个StreamController
来管理数据流。例如,当一个按钮被点击,需要更新UI状态时,可以通过StreamController
的add
方法发送新的数据。 -
class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { final StreamController<int> _counterController = StreamController<int>(); int _counter = 0; @override void initState() { super.initState(); _counterController.stream.listen((count) { setState(() { _counter = count; }); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Stream with StatefulWidget')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text('You have pushed the button this many times:'), StreamBuilder<int>( stream: _counterController.stream, initialData: _counter, builder: (context, snapshot) { return Text('${snapshot.data}', style: Theme.of(context).textTheme.headline4); }, ) ], ), ), floatingActionButton: FloatingActionButton( onPressed: () { _counterController.add(_counter + 1); }, tooltip: 'Increment', child: Icon(Icons.add), ), ); } @override void dispose() { _counterController.close(); super.dispose(); } }
- 在
- 使用BLoC:
- 创建一个BLoC类,该类负责处理业务逻辑和管理状态。例如,对于一个用户登录功能,BLoC可以处理登录请求、验证以及状态更新。
- 在
StatefulWidget
的State
类中,通过BlocProvider
提供BLoC实例,并使用BlocBuilder
来监听BLoC的状态变化从而更新UI。 -
// BLoC class class LoginBloc extends Bloc<LoginEvent, LoginState> { @override LoginState get initialState => LoginInitial(); @override Stream<LoginState> mapEventToState(LoginEvent event) async* { if (event is LoginButtonPressed) { yield LoginLoading(); try { // 模拟登录请求 await Future.delayed(Duration(seconds: 2)); yield LoginSuccess(); } catch (e) { yield LoginFailure('Login failed'); } } } } // Events abstract class LoginEvent {} class LoginButtonPressed extends LoginEvent {} // States abstract class LoginState {} class LoginInitial extends LoginState {} class LoginLoading extends LoginState {} class LoginSuccess extends LoginState {} class LoginFailure extends LoginState { final String error; LoginFailure(this.error); } // StatefulWidget class LoginPage extends StatefulWidget { @override _LoginPageState createState() => _LoginPageState(); } class _LoginPageState extends State<LoginPage> { @override Widget build(BuildContext context) { return BlocProvider( create: (context) => LoginBloc(), child: Scaffold( appBar: AppBar(title: Text('Login Page')), body: BlocBuilder<LoginBloc, LoginState>( builder: (context, state) { if (state is LoginInitial) { return Center( child: RaisedButton( onPressed: () { BlocProvider.of<LoginBloc>(context).add(LoginButtonPressed()); }, child: Text('Login'), ), ); } else if (state is LoginLoading) { return Center(child: CircularProgressIndicator()); } else if (state is LoginSuccess) { return Center(child: Text('Login Success')); } else if (state is LoginFailure) { return Center(child: Text(state.error)); } return Container(); }, ), ), ); } }
2. 结合在解决复杂业务逻辑时的优势
- 解耦UI与业务逻辑:在实际案例中,比如一个电商应用的购物车功能。使用BLoC模式,购物车的添加、删除商品等业务逻辑都在BLoC中处理,UI只需要监听BLoC的状态变化。这样当业务逻辑发生改变,比如添加商品时需要进行库存检查等新逻辑,只需要修改BLoC代码,而UI代码无需变动,大大提高了代码的可维护性。
- 可测试性增强:对于上述购物车BLoC,可以单独对BLoC进行单元测试,验证各种业务逻辑的正确性。例如,测试添加商品时购物车总价的计算是否正确,而不需要依赖于UI。这使得测试更加简单和高效,能够更快地发现和修复问题。
- 代码复用性提高:同样以电商应用为例,购物车BLoC可以在不同的页面(如商品详情页添加到购物车、购物车页面管理商品等)复用。只要提供相同的输入事件,BLoC就能处理并返回相应的状态,减少了重复代码,提高了开发效率。