4

I want to run a function every time the page changes in my Flutter application.

Ideally, I don't want to call this function in initState of every page, as sometimes people can forget to add the call in a new page.

Think of it as middleware - be basically before the page loads etc, some code needs to run.

Updated code for review

import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:myapp/pages/login_page.dart';
import 'package:myapp/pages/dashboard_page.dart';
import 'package:myapp/styles/constants.dart';
import 'package:myapp/services/auth_service.dart';

Future<void> main() async {
  // create a auth service instance
  AuthService authService = AuthService(secureStorage: FlutterSecureStorage());
  bool isLoggedIn = await authService.isUserLoggedIn();

  // run the app
  runApp(MyApp(
    isLoggedIn: isLoggedIn,
  ));
}

class MyApp extends StatefulWidget {
  final bool isLoggedIn;

  MyApp({this.isLoggedIn});

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with RouteAware {
  final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    routeObserver.subscribe(this, ModalRoute.of(context));
  }

  @override
  void dispose() {
    routeObserver.unsubscribe(this);
    super.dispose();
  }

  @override
  void didPush() {
    print('didPush');
  }

  @override
  void didPopNext() {
    print('didPopNext');
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'App NAME',
      theme: ThemeData(
        primarySwatch: Colors.green,
        primaryColor: kPrimeColour,
      ),
      home: widget.isLoggedIn == true ? DashboardPage() : LoginPage(),
      navigatorObservers: [routeObserver],
    );
  }
}

Billy Mahmood
  • 1,857
  • 5
  • 26
  • 37
  • The `build` method is responsible for changing the widget/page content. which means that you only need to call your function in the `build` method – Raouf Rahiche Aug 01 '19 at 10:41
  • 1
    Hey, my application currently has more than 8 pages, which means I have more than 8 build methods, and as the application grows, we need to make sure that this functionality runs on all new pages - is this possible, if so please can you give an example? – Billy Mahmood Aug 01 '19 at 10:47
  • 1
    I need to exactly understand your case I think you are just looking for [RouteObserver](https://api.flutter.dev/flutter/widgets/RouteObserver-class.html) which will be triggered every time a new route/page will be pushed or poped – Raouf Rahiche Aug 01 '19 at 10:52
  • This is just what I need, the docs on it are slightly over my head, however, I will try to make sense of it - and if I cant, I will be back – Billy Mahmood Aug 01 '19 at 11:03
  • So I am able to add the routeObserver to main() - am not sure how to add the event listeners, without amending existing pages, any suggestions on this please? – Billy Mahmood Aug 01 '19 at 11:11
  • Check out this [example](https://medium.com/@najeira/how-to-handle-screen-transitions-in-flutter-b39dcb2675f) – Raouf Rahiche Aug 01 '19 at 11:19

2 Answers2

6

You can use implementation method didChangeDependencies this function called after initState,

flutter doc :

Subclasses rarely override this method because the framework always calls build after a dependency changes. Some subclasses do override this method because they need to do some expensive work (e.g., network fetches) when their dependencies change, and that work would be too expensive to do for every build.

Link

    @override
    void didChangeDependencies() {
      super.didChangeDependencies();
      // set your stuff here 
      }
4

You can use inheritance

abstract class MyState<T extends StatefulWidget> extends State {
  @override
  void initState() {
    super.initState();
    //YOUR CHANGE PAGE METHOD HERE
  }
}

class YellowBird extends StatefulWidget {
  const YellowBird({ Key key }) : super(key: key);

  @override
  _YellowBirdState createState() => _YellowBirdState();
}

class _YellowBirdState extends MyState<YellowBird> {
  @override
  Widget build(BuildContext context) {
    return Container(color: const Color(0xFFFFE306));
  }
}
gersur
  • 187
  • 3
  • 10