Error T is not a function when trying to call class constructor from a dart mixin

Viewed 338

I currently have a simple mixin like this:

import 'package:flutter/material.dart';

mixin PageNav on StatefulWidget {
  pushPage(BuildContext context) {
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => this)
    );
  }
}

This mixin saves me from having to define a pushPage method in the StatefullWidget of every "page". So it eliminates the following boilerplate:

class PageTwo extends StatefulWidget {
  static pushPage(BuildContext context) {
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => PageTwo())
    );
  }
  @override
  _PageTwoState createState() => _PageTwoState();
}

Notice that the method is static and calls the StatefulWidget constructor.

Thus the mixin is used like this (on any other page or widget where the user may navigate to):

class PageOne extends StatefulWidget with PageNav {
  @override
  _PageOneState createState() => _PageOneState();
}

and then somewhere else from where the user could be navigating to this page:

                TextButton(
                  onPressed: () => PageOne().pushPage(context),
                  child: Text('Go to PageOne'),
                ),

This works and is OK, but it would be even nicer if I could do, as is possible with the PageTwo example, the following:

                TextButton(
                  onPressed: () => PageOne.pushPage(context),
                  child: Text('Go to PageOne'),
                ),

Here pushPage is a static member, so the mixin definition would need to change...

I tried the following but it baulks:

import 'package:flutter/material.dart';

mixin PageNav<T> on StatefulWidget {
  static pushPage(BuildContext context) {
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => T()) // Error: T isn't a function
    );
  }
}

So how do I access the constructor (or even other static methods) of the class on which the mixin is applied (from a static method)?

1 Answers

If your goal is just to avoid writing the boilerplate for using Navigator.push(),
then there are 2 ways you can get this done.

  1. You can either use the GetX package which has simple interface like Get.to(() => Page2()); (Yes, without BuildContext)

  2. You can simply create a static method in a utility class like below & call it without initialising a class:

class PageNavigator {
  static pushPage(BuildContext context, Widget destination) {
    Navigator.push(
        context,
        MaterialPageRoute(builder: (_) => destination));
  }
}

Use it like: PageNavigator.pushPage(context, MainScreen())

Related