Search code examples
flutterflutter-dependenciesback-stack

Flutter :- How manage the backstack like in Android "SingleTask"?


I am trying to manage the backstack in Flutter like in Android we manage it from launchMode (eg. SingleTask,SingleTop , Standard etc..) , For it i have tried the Routes in flutter, but did not get the success, please check the below code, which i have tried to achieve the backstack.

Widget makeRoute(
    {@required BuildContext context,
    @required String routeName,
    Object arguments}) {
  final Widget child =
      _buildRoute(context: context, routeName: routeName, arguments: arguments);
  return child;
}

Widget _buildRoute({
  @required BuildContext context,
  @required String routeName,
  Object arguments,
}) {
  switch (routeName) {
    case '/':
      return SplashScreen();

    case '/A':              //// NAME OF SCREEN IS A
      return A();

    case '/B':              //// NAME OF SCREEN IS B
      MyBean docs = arguments as MyBean;
      return B(dataToShow: docs);

    case '/C':              //// NAME OF SCREEN IS C
      MyBean docs = arguments as MyBean;
      return C(dataToShow: docs);

    case '/D':             //// NAME OF SCREEN IS D
      return D();


  }
}

I am jumping the screens from A->B->C->D are as follow,
From A->B , I navigate it like below.

Navigator.of(context).pushNamed('/B');

From B->C , I navigate it like below.

 Navigator.of(context).pushNamed('/C', arguments: myList[index]);

And finally, From C->D , I navigate it like below.

Navigator.of(context).pushNamed('/D');

As from the above code, I successfully navigated to the A------>D screens and also carrying data successfully.

But my main concern is that i want to navigate from the D->A or D->B screen using the backstack without opening another screen, So i have tried the below code but it is not working , please check the below code.

From D->A, I have tried like

Navigator.popUntil(context, ModalRoute.withName('/A'));

And even tried in this manner like below.

 Navigator.of(context)
          .popUntil(ModalRoute.withName("/A"));

I even this way to manage the flow like below

 SchedulerBinding.instance.addPostFrameCallback((_) {
                      Navigator.popUntil(context, ModalRoute.withName('/A'));

                    });

But both are not working properly
Please check my main() class

void main() {
  runApp(
      MaterialApp(
        debugShowCheckedModeBanner: false,
        title: '',
        theme: ThemeData(
          brightness: Brightness.light,
          primarySwatch: Colors.grey,
          primaryColor: ColorConst.PRIMARY_COLOR,
          accentColor: ColorConst.ACCENT_COLOR,
          primaryColorBrightness: Brightness.light,


          accentColorBrightness: Brightness.light,
        ),

          onGenerateRoute: (RouteSettings settings) {
            return MaterialPageRoute(
              builder: (BuildContext context) => makeRoute(
                context: context,
                routeName: settings.name,
                arguments: settings.arguments,
              ),
              maintainState: true,
              fullscreenDialog: false,
            );
          }

      )
  );
}

And getting the following exception from above code like below.

═ (2) Exception caught by widgets library ═══════════════════════════════════════════════════
'package:flutter/src/widgets/navigator.dart': Failed assertion: line 2330 pos 12: '!_debugLocked': is not true.
The relevant error-causing widget was: 
  MaterialApp **file:///Users/apple/Documents/BitBucket%20Projects/loyalityapp_android/lib/main.dart:10:7**
════════════════════════════════════════════════════════════════════════════════════════════════════

Getting execption while navigate from the D->A


Solution

  • I have solved the problem by using the MaterialPageRoute and referred this link to get the solution Click here

    From A->B->C->D screen navigation, I have used this approach

    From A->B screen

     Navigator.push(
                        context,
                        MaterialPageRoute(
                          settings: RouteSettings(name: "B"),
                          builder:  (context) => SCREEN_B(),
                        ),
                      );
    

    And from B->C, I haved used this along with parameters like below

     Navigator.push(
                  context,
                  MaterialPageRoute(
                    settings: RouteSettings(name: "C"),
                    builder:  (context) => SCREEN_C(dataToShow:myList[index]),
                  ),
                );
    

    From C->D screen

     Navigator.push(
                        context,
                        MaterialPageRoute(
                          settings: RouteSettings(name: "D"),
                          builder:  (context) => SCREEN_D(),
                        ),
                      );
    

    And main logic is here navigations from D->A or D->B, from below liens of code

    Navigator.popUntil(context, ModalRoute.withName("A"));  //YOU CAN USE "B" TO NAVIGATE
    

    At the last one more thing which I need to add here is that when I want to perform any action like refresh activity and anything else from screen D->A Then inside the A screen, we need to use then method like below

    Navigator.push(
              context,
              MaterialPageRoute(
                settings: RouteSettings(
                    name: "B"),
                builder: (context) =>
                    B(dataToShow: MYLIST[index]),
              ),
            ).then((value) {
              //// THIS METHOD IS ENVOKE WHEN SCREEN COME FROM D->A OR B->A, YOU CAN PERFROM CAN TASK HERE
            });