不受上下文干扰的导航

时间:2020-08-09 08:55:25

标签: flutter dart

我创建了一个服务文件夹,并在其中创建了一个名为request的文件。 dart,在这里我打算将所有发出的请求放入一个名为AuthService的类中,下面的登录请求是我希望能够在一次response.statusCode == 200或201的情况下导航到主屏幕,但是我不能这样做,因为导航需要上下文,并且我的课程既不是有状态的窗口小部件,也不是无状态的小部件,没有上下文,有什么方法可以导航?

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/material.dart';

class AuthService {

  login(email, password) async {
    SharedPreferences sharedPreferences = await SharedPreferences.getInstance();

    if (email == "" && password == "") {
      return;
    }

    try {
      Map data = {'email': email, 'password': password};

      var jsonResponse;
      var response = await http
          .post('https://imyLink.com/authenticate', body: data);
      if (response.statusCode == 200 || response.statusCode == 201) {

//I want to navigate to my home screen once the request made is successful

        jsonResponse = json.decode(response.body);
        if (jsonResponse != null) {
          await sharedPreferences.setString("userToken", jsonResponse["token"]);
          var token = sharedPreferences.getString("userToken");
          print('Token: $token');
          print(jsonResponse);
          print("Login successful");
        }
      } else {
        print(response.statusCode);
        print('Login Unsuccessful');
        print(response.body);
      }
    } catch (e) {
      print(e);
    }
}

4 个答案:

答案 0 :(得分:2)

首先,创建一个类

import 'package:flutter/material.dart';

class NavigationService{
  GlobalKey<NavigatorState> navigationKey;

  static NavigationService instance = NavigationService();

   NavigationService(){
     navigationKey = GlobalKey<NavigatorState>();
   }

  Future<dynamic> navigateToReplacement(String _rn){
return navigationKey.currentState.pushReplacementNamed(_rn);
  }
 Future<dynamic> navigateTo(String _rn){
   return navigationKey.currentState.pushNamed(_rn);
  }
 Future<dynamic> navigateToRoute(MaterialPageRoute _rn){
   return navigationKey.currentState.push(_rn);
  }

 goback(){
   return navigationKey.currentState.pop();

  }
  }

在您的main.dart文件中。

 MaterialApp(
  navigatorKey: NavigationService.instance.navigationKey,
  initialRoute: "login",
  routes: {
    "login":(BuildContext context) =>Login(),
    "register":(BuildContext context) =>Register(),
    "home":(BuildContext context) => Home(),

  },
);

然后,您可以从项目中的任何地方调用该函数,例如...

 NavigationService.instance.navigateToReplacement("home");
 NavigationService.instance.navigateTo("home");

答案 1 :(得分:1)

选项1

如果要在loginStateful小部件中调用Stateless方法。您可以将context作为参数传递给login类的AuthService方法。

我以您的代码为例添加了一个演示:

class AuthService {

  // pass context as a parameter
  login(email, password, context) async {
    SharedPreferences sharedPreferences = await SharedPreferences.getInstance();

    if (email == "" && password == "") {
      return;
    }

    try {
      Map data = {'email': email, 'password': password};

      var jsonResponse;
      var response = await http
          .post('https://imyLink.com/authenticate', body: data);
      if (response.statusCode == 200 || response.statusCode == 201) {

      //I want to navigate to my home screen once the request made is successful
      Navigator.of(context).push(YOUR_ROUTE); // new line

        jsonResponse = json.decode(response.body);
        if (jsonResponse != null) {
          await sharedPreferences.setString("userToken", jsonResponse["token"]);
          var token = sharedPreferences.getString("userToken");
          print('Token: $token');
          print(jsonResponse);
          print("Login successful");
        }
      } else {
        print(response.statusCode);
        print('Login Unsuccessful');
        print(response.body);
      }
    } catch (e) {
      print(e);
    }
}

选项2

如果您使用的是“命名路线”,则可以通过设置MaterialApp的navigatorKey属性来访问应用程序的导航器而无需上下文:

  /// A key to use when building the [Navigator].
  ///
  /// If a [navigatorKey] is specified, the [Navigator] can be directly
  /// manipulated without first obtaining it from a [BuildContext] via
  /// [Navigator.of]: from the [navigatorKey], use the [GlobalKey.currentState]
  /// getter.
  ///
  /// If this is changed, a new [Navigator] will be created, losing all the
  /// application state in the process; in that case, the [navigatorObservers]
  /// must also be changed, since the previous observers will be attached to the
  /// previous navigator.
  final GlobalKey<NavigatorState> navigatorKey;

创建密钥:

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

将其传递给MaterialApp:

new MaterialApp(
      title: 'MyApp',
      onGenerateRoute: generateRoute,
      navigatorKey: key,
    );

推路线:

navigatorKey.currentState.pushNamed('/someRoute');

按照以下github问题查找有关选项2的更多详细信息:https://github.com/brianegan/flutter_redux/issues/5#issuecomment-361215074

答案 2 :(得分:0)

您可以使用颤抖的Get软件包。

Here is link

答案 3 :(得分:0)

您可以使用此插件跳过所需的上下文

https://pub.dev/packages/one_context

// go to second page using named route
OneContext().pushNamed('/second');
// go to second page using MaterialPageRoute
OneContext().push(MaterialPageRoute(builder: (_) => SecondPage()));
// go back from second page
OneContext().pop();