omar developer
omar developer

Reputation: 197

How to Navigate without context in flutter?

I ended up with using a static function but I need to do navigation and It gave me an error that no getter was found for context so I looked for a solution and found the GET package but when I tried to use it It gave me another error :

E/flutter ( 6078): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] 
Unhandled Exception: NoSuchMethodError: The method 'push' was called on null.

My code:

    void main() {
      runApp(MyApp());
      _MyAppState.autologin();
    }
    
    class _MyAppState extends State<MyApp> {
      static autologin() async {
        var userType;
        var store = Firestore.instance;
        var auth = FirebaseAuth.instance;
        final FirebaseUser user = await auth.currentUser();
        store.collection('Users').document(user.uid).get().then((value) {
          userType = (value.data)['userType'];
          if (userType == 'Student') {
            Get.to(StudentsPage());
          } else if (userType == 'Teacher') {
          } else if (userType == 'Admin') {}
        });
      }

Upvotes: 4

Views: 7448

Answers (2)

Yusuf Amr
Yusuf Amr

Reputation: 587

This solution is general if you want to navigate or to show Dialog without context using globalKey especially with Bloc or when your logic is separated from your UI part.

Firstly install this package:

Note: I'm using null safety version

  get_it: ^7.2.0

Then create a separate file for your service locator:

service_location.dart

    import 'package:get_it/get_it.dart';
    
    GetIt locator = GetIt.instance;
    
    class NavigationService {
      final GlobalKey<NavigatorState> navigatorKey =
          new GlobalKey<NavigatorState>();
      Future<dynamic> navigateTo(String routeName) {
        return navigatorKey.currentState!.pushNamed(routeName);
      }
    
      void setupLocator() {
        locator.registerLazySingleton(() => NavigationService());
      }

  void showMyDialog() {
    showDialog(
        context: navigatorKey.currentContext!,
        builder: (context) => Center(
              child: Material(
                color: Colors.transparent,
                child: Text('Hello'),
              ),
            ));
  }
    }

on main.dart:

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  NavigationService().setupLocator();
  runApp(MyApp());
}
// add navigatorKey for MaterialApp

 MaterialApp(
        navigatorKey: locator<NavigationService>().navigatorKey,
      ),

at your business logic file bloc.dart define this inside the bloc class or at whatever class you want to use navigation inside Then start to navigate inside any function inside.

class Cubit extends Cubit<CubitState> {
  final NavigationService _navigationService = locator<NavigationService>();
  void sampleFunction(){
       _navigationService.navigateTo('/home_screen'); // to navigate
       _navigationService.showMyDialog(); // to show dialog

    }
}

Not: I'm using generateRoute for routing.

Upvotes: 0

Murat Aslan
Murat Aslan

Reputation: 1580

Create a navigator key

final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

Assign it to MaterialApp

MaterialApp(
    home: Home(),
    navigatorKey: navigatorKey
),

Then push your routes by navigatorKey below

navigatorKey.currentState.push(MaterialPageRoute(
    builder: (context) => AnotherPage(),
));

or

navigatorKey.currentState.pushNamed(routeName);

Upvotes: 8

Related Questions