我一直在尝试使用Flutter构建应用程序,但是我很难弄清Flutter中的某些概念。我希望在这里找到一些答案。
前言: 应用依存关系: flutter_mobx,自动路由,get_it 。
我正在构建一个需要显示警报的应用程序。我创建了一个Flutter页面(AlertsScreen
),该页面已订阅 mobx alerts_store 。因此,每当我尝试向 alerts_store 发出警报时,小吃栏都应弹出。与我在React web中所做的类似。
应用回购链接:https://github.com/ganeshrvel/open_cloud_encryptor/tree/new-router-logic
问题:
AlertsScreen()
之类的通用小部件,该小部件将在整个应用程序中呈现。
以前我曾经做过这样的事情:app.dart(Github link)
MaterialApp(
builder: (BuildContext context, Widget widget) {
setErrorBuilder();
return Column(
children: <Widget>[
Expanded(
child: widget,
),
AlertsScreen(),
],
);
},
title: 'App name',
onGenerateRoute: Router.onGenerateRoute,
initialRoute: Router.splashScreen,
navigatorKey: Router.navigator.key,
),
但是,每当我尝试在AlertsScreen中渲染Flushbar或任何其他需要context
的项目时,都会引发错误:
[ERROR:flutter / lib / ui / ui_dart_state.cc(157)]未处理的异常: 请求的导航器操作的上下文不包含 航海家。用于从导航器推送或弹出路由的上下文 必须是作为导航器小部件的后代的小部件。
Flushbar示例代码:
Flushbar(title: 'title',message: 'body',duration: const Duration(seconds: 5),).show(context);
如何在应用程序中安装AlertsScreen
之类的通用小部件,并且对于任何类型的活动始终可见?
2)这个来自stackoverflow的answer建议制作一个CommonWidget无状态小部件,并在需要呈现的地方使用它。 因此,从上述stackoverflow答案中获取线索,我将代码修改如下:
common_widget.dart(Github link)
class CommonWidget extends StatelessWidget {
final Widget child;
const CommonWidget({
@required this.child,
});
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
child: child,
),
AlertsScreen(),
],
);
}
}
home.dart(Github link)
class _HomeScreenState extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
),
body: CommonWidget(
child: Center(
child: Column(),
),
),
);
}
}
这是正确的方法吗?
3)我使用 flutter_mobx 作为AlertsScreen
的商店。由于我已在多个屏幕上使用CommonWidget来显示AlertsScreen
,因此,每当我更新商店时,AlertsScreen都会多次重建。我该如何预防?如何确保AlertsScreen
小部件仅在当前屏幕中重新呈现,并防止它在更新商店时在其他任何地方重建?
当前的解决方法是这样的:
alerts.dart(Github Link)
@override
void didChangeDependencies() {
super.didChangeDependencies();
_alertsStore ??= Provider.of<AlertsStore>(context);
_disposers ??= [
reaction(
(_) => _alertsStore.alertsList.iterator,
(alertsList) {
if (ModalRoute.of(context).isCurrent) { // Check whether current screen is rendered
buildSnackbar();
}
},
),
];
}
还有更好的方法吗?