Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global snackbar/dialog utils class in flutter

Tags:

flutter

I want to create a GlobalMessageUtils class that would open a material snackbar or dialog without having to pass the build context. The idea is that whenever there's any error (no network, bad request, etc) I am able to pop open a snackbar and relay the message to the user.Is there a concept of global context?

I was playing with the idea of making my GlobalMessageUtils class a singleton that takes in a build context and instantiate it at the MaterialApp level, but I haven't gotten this to work. Any body have any ideas? Is this even a good pattern in flutter? If not, how do you guys deal with error handling at a global level?

like image 364
baby.zard Avatar asked Mar 10 '19 00:03

baby.zard


People also ask

How do I show SnackBar without context in Flutter?

then you can simply call the Get. snackbar() to show the snackbar where you want it to be displayed. You can use this package when you don't have the context too. Save this answer.

How do I show SnackBar message in Flutter?

The ElevatedButton is a child widget placed on the return Center . Then, we use the ScaffoldMessenger class to display the SnackBar. Clicking on the button will show the SnackBar with the following message: “Hi, I am a SnackBar!”


1 Answers

Using the BLOC pattern and Rxdart, I created a UiErrorUtils class

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

In your StatefulWidget, you can use the context provided in the initState hook:

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();
  }
}

Now your widget has subscribed to the bloc's snackBarStream. So in your bloc whenever a request fails you can add the message to the snackBarStream and since your widget has subscribed via UiErrorUtils the snackbar will trigger with the message.

like image 92
baby.zard Avatar answered Nov 09 '22 06:11

baby.zard