【问题标题】:Global snackbar/dialog utils class in flutterFlutter 中的全局小吃吧/对话框实用程序类
【发布时间】:2019-03-10 00:04:50
【问题描述】:

我想创建一个GlobalMessageUtils 类,该类将打开一个材料小吃栏或对话框,而无需传递构建上下文。这个想法是,每当出现任何错误(无网络、错误请求等)时,我都可以弹出一个快餐栏并将消息转发给用户。有全局context 的概念吗?

我的想法是让我的GlobalMessageUtils 类成为一个接收构建context 并在MaterialApp 级别实例化它的单例,但我还没有让它工作。任何机构有任何想法?这甚至是颤振的好模式吗?如果没有,你们如何处理全局级别的错误处理?

【问题讨论】:

  • 你在这个问题中发现了什么吗??
  • @ZainSMJ 我找到了一种模式来代替全局上下文。请参阅下面的答案

标签: flutter


【解决方案1】:

使用 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);

  }

}

集团

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。 因此,在您的 bloc 中,每当请求失败时,您都可以将消息添加到snackBarStream,并且由于您的小部件已通过UiErrorUtils 订阅,因此snackbar 将随消息一起触发。

【讨论】:

    【解决方案2】:

    我写了一个支持应用程序范围消息显示的包。

    EZ Flutter 支持通过一行代码从应用内的任何位置向用户显示消息。全局消息由 BLOC 处理,小部件作为 Scaffold 的主体添加。

    Github:https://github.com/Ephenodrom/EZ-Flutter

    dependencies:
      ez_flutter: ^0.2.0
    

    添加消息包装器

    EzGlobalMessageWrapper 作为主体添加到脚手架。

    Scaffold{
      appBar: ...
      body: EzGlobalMessageWrapper(
        MyWidget(
          ...
        )
      )
    }
    

    向集团添加消息

    使用 get 方法通过EzBlocProvider 加载EzMessageBloc

    EzMessage 添加到该集团。支持的EzMessageTypes 是:

    • 成功(默认颜色:Colors.green)
    • 信息(默认颜色:Colors.blue)
    • 警告(默认颜色:Colors.orange)
    • 错误(默认颜色:Colors.red)
        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

    【讨论】:

      【解决方案3】:

      对于 Provider 解决方案,如果您使用 BaseWidget,那么您只需创建一个基类方法并在您使用 provider 的任何地方使用它。

          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');
      

      【讨论】:

        【解决方案4】:
        1. 定义全局变量,例如里面main.dart
        final GlobalKey<ScaffoldMessengerState> rootScaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
        
        1. MaterialApp 小部件具有 scaffoldMessengerKey 属性,因此将此键设置为属性
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          scaffoldMessengerKey: rootScaffoldMessengerKey,
          home: Scaffold(),
        );
        
        1. 现在您可以在应用中的任何位置显示SnackBar
        rootScaffoldMessengerKey.currentState?.showSnackBar(SnackBar(content: Text('some text')));
        

        【讨论】:

          猜你喜欢
          • 2016-03-17
          • 2021-12-09
          • 2021-05-13
          • 2019-07-25
          • 2020-10-29
          • 2020-09-07
          • 2018-07-03
          • 2021-10-24
          • 1970-01-01
          相关资源
          最近更新 更多