我想创建一个GlobalMessageUtils
类,该类将打开一个材质小吃栏或对话框而无需传递构建上下文。这样的想法是,每当发生任何错误(没有网络,错误的请求等)时,我都可以弹出小吃栏并将消息转发给用户。是否有全局context
的概念?
我一直在想让我的GlobalMessageUtils
类成为一个单例,该单例需要一个构建context
并在MaterialApp
级别对其进行实例化,但是我还没有想到工作。任何机构有什么想法?这甚至是扑打的好模式吗?如果没有,你们如何在全球范围内处理错误处理?
答案 0 :(得分:0)
使用BLOC模式和Rxdart,我创建了一个UiErrorUtils
类
class UiErrorUtils {
// opens snackbar
void openSnackBar(BuildContext context, String message) async {
await Scaffold.of(context).showSnackBar(
SnackBar(
content: Text(message),
),
);
}
// subscribes to stream that triggers open snackbar
void subscribeToSnackBarStream(BuildContext context, PublishSubject<String> stream){
stream.listen((String message){
openSnackBar(context, message);
});
}
}
在您的StatefulWidget中,您可以使用initState
钩中提供的上下文:
class WidgetThatUsesUIErrorUtils extends StatefulWidget {
final UiErrorUtils uiErrorUtils;
final Bloc bloc;
WidgetThatUsesUIErrorUtils({this.uiErrorUtils, this.bloc});
WidgetThatUsesUIErrorUtils createState() => WidgetThatUsesUIErrorUtilsState(
uiErrorUtils: uiErrorUtils,
bloc: bloc,
);
}
class WidgetThatUsesUIErrorUtilsState extends State<WidgetThatUsesUIErrorUtils> {
final Bloc _bloc;
final UiErrorUtils _uiErrorUtils;
WidgetThatUsesUIErrorUtilsState({Bloc bloc, UiErrorUtils uiErrorUtils})
: _bloc = bloc ?? Bloc(),
_uiErrorUtils = uiErrorUtils ?? UiErrorUtils();
@override
void initState() {
super.initState();
// Subscribe to UI feedback streams from provided _bloc
_uiErrorUtils.subscribeToSnackBarStream(context, _bloc.snackBarSubject);
}
}
BLOC
class Bloc extends BlocBase {
// UI Feedback Subjects
final PublishSubject<String> snackBarSubject = PublishSubject<String>();
// some function that gets data from network
Future<bool> getDataRequest() async {
try {
// get request code here
} catch(error) {
this.snackBarSubject.add(error);
}
}
@override
void dispose() {
snackBarSubject?.close();
}
}
现在,您的窗口小部件已订阅了该集团的SnackBarStream。
因此,在您的集团中,每当请求失败时,您都可以将消息添加到SnackBarStream中,并且由于您的窗口小部件已通过UiErrorUtils
进行了订阅,所以SnackBar会随消息触发。
答案 1 :(得分:0)
我写了一个支持应用程序范围内消息显示的包。
EZ Flutter支持仅使用一行代码就可以从应用程序内的任何位置向用户显示消息。全局消息是通过BLOC处理的,并且将小部件添加为脚手架的主体。
Github:https://github.com/Ephenodrom/EZ-Flutter
dependencies:
ez_flutter: ^0.2.0
将EzGlobalMessageWrapper作为主体添加到支架中。
Scaffold{
appBar: ...
body: EzGlobalMessageWrapper(
MyWidget(
...
)
)
}
使用 get 方法通过EzMessageBloc加载EzBlocProvider。
向集团添加EzMessage。受支持的EzMessageTypes是:
EzBlocProvider.of<EzGlobalBloc>(context)
.get<EzMessageBloc>(EzMessageBloc)
.addition
.add(EzMessage("This is a success message", EzMessageType.SUCCESS));
https://github.com/Ephenodrom/EZ-Flutter/blob/master/documentation/GLOBAL_MESSAGE.md
答案 2 :(得分:0)
对于提供程序解决方案,如果您使用 BaseWidget,那么您只需创建一个基类方法并在您使用提供程序的任何地方使用它。
class BaseWidget<T extends ChangeNotifier> extends StatefulWidget {
final Widget Function(BuildContext context, T model, Widget child) builder;
.
.
.
showToast(BuildContext context, String message, {int durationSeconds = 5}) {
final ScaffoldMessengerState scaffoldMessenger =
ScaffoldMessenger.of(context);
scaffoldMessenger.showSnackBar(SnackBar(
content: Text(message),
duration: Duration(seconds: durationSeconds),
action: SnackBarAction(
label: 'HIDE',
onPressed: () {
scaffoldMessenger.hideCurrentSnackBar();
},
)));
}
然后从您的视图中调用它。
.
.
.
showToast(context, "Factor Model Created Successfully",
durationSeconds: 30);
Navigator.pop(context, 'save');
答案 3 :(得分:0)
main.dart
final GlobalKey<ScaffoldMessengerState> rootScaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
MaterialApp
小部件具有 scaffoldMessengerKey
属性,因此将此键设置为属性return MaterialApp(
debugShowCheckedModeBanner: false,
scaffoldMessengerKey: rootScaffoldMessengerKey,
home: Scaffold(),
);
SnackBar
rootScaffoldMessengerKey.currentState?.showSnackBar(SnackBar(content: Text('some text')));