How to write a mixin for a generic class State<T extends StatefulWidget>

3,157

I think you are looking for something like https://github.com/flutter/flutter/blob/3fbd140e77601686acb336cd2af2838d03ba0572/packages/flutter/lib/src/widgets/ticker_provider.dart#L155

mixin BaseState<T extends StatefulWidget> on State<T> {
Share:
3,157
Martin.
Author by

Martin.

ಠ,ಠ

Updated on December 09, 2022

Comments

  • Martin.
    Martin. over 1 year

    I'm in need to write an extension for Flutter's State<T extends StatefulWidget> so I can use a function in all of my States, let's say showSnackBar("Hello world", 5). I tried writing a mixin

    mixin BaseState on State<ProfileScreen> {
      final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();
    
      void showSnackBar(String text) {
        setState(() {
          scaffoldKey.currentState.showSnackBar(new SnackBar(
              content: new Row(
                children: <Widget>[
                  new CircularProgressIndicator(),
                  new Text(text == null ? "  Logging in" : "      $text")
                ],
              )));
        });
      }
    
      void hideSnackBar() {
        setState(() {
          scaffoldKey.currentState.hideCurrentSnackBar();
        });
      }
    }
    

    As you can see, it is now mixed on State<ProfileScreen>. It's a problem because I only can use this mixin in class ProfileScreenState extends State<ProfileScreen>. Without the type notation I end up with an error:

    error: The class 'ProfileScreenState' cannot implement both 'State<ProfileScreen>' and 'State<StatefulWidget>' because the type arguments are different. (conflicting_generic_interfaces at [mobile] lib/Screens/profile.dart:17)
    error: Type parameters could not be inferred for the mixin 'BaseState' because no type parameter substitution could be found matching the mixin's supertype constraints (mixin_inference_no_possible_substitution at [mobile] lib/Screens/profile.dart:17)
    

    I tried to Google a lot, seen questions like these but without a success.

    And yes I know composition is preferred over inheritance in Flutter, but I think this is a thing I don't know I would make work with composition and I feel it will be OK with inheritance.

  • Martin.
    Martin. over 5 years
    I was very close with mixin BaseState<T extends StatefulWidget> on State<T extends StatefulWidget> {. Thanks a lot! Anyway, what in case I would like to, at some point, mixin it into StatelessWidget, is there a quick trick to accept that as well?
  • Günter Zöchbauer
    Günter Zöchbauer over 5 years
    mixin BaseStateless<T extends StatelessWidget> on StatelessWidget { or mixin BaseStateless<T extends StatelessWidget> on T { should do
  • Martin.
    Martin. over 5 years
    that is a mixing for Stateless, what if I want to share a functionality for both StatefulWidget and StatelessWidget in one mixin? Does that make sense?
  • Martin.
    Martin. over 5 years
    I mean something like mixin BaseState<T extends StatefulWidget or StatelessWidget> on State<T> {
  • Günter Zöchbauer
    Günter Zöchbauer over 5 years
    I think in this case you'd need to remove on X...
  • Martin.
    Martin. over 5 years
    That does cut off the possibility to use the functions from StatelessWidget and StatefulWidget. It's true tho that it probably won't make any sense since StatefulWidget has setState and StatelessWidget has not
  • Günter Zöchbauer
    Günter Zöchbauer over 5 years
    They State<T> and StatelessWidget do not have a common interface so this can't work with the same mixin.