【问题标题】:Why my observable variable can not update the "main.dart" in Flutter using GetX?为什么我的可观察变量无法使用 GetX 更新 Flutter 中的“main.dart”?
【发布时间】:2022-02-06 12:23:30
【问题描述】:

以下代码是我的auth_controller.dart 代码。我看到 response 来自后端工作,这是预期的结果,在我提交表单后,tokenisAuth 值更改为 true

enum AuthMode { Signup, Login }

class AuthController extends GetxController
    with GetSingleTickerProviderStateMixin {
  static AuthController instance = Get.find();
  Rx<dynamic>? authMode = AuthMode.Login.obs;
  RxBool? isLoading = false.obs;
  String? _token;
  DateTime? _expiryDate;
  String? _userId;
  Timer? _authTimer;
  final _isAuth = false.obs;

  AnimationController? controller;
  Animation<Offset>? slideAnimation;
  Animation<double>? opacityAnimation;
  // late TextEditingController passwordController;
  // final key = GlobalKey<FormState>();

  @override
  void onInit() {
    super.onInit();
    controller = AnimationController(
      vsync: this,
      duration: const Duration(
        milliseconds: 300,
      ),
    );
    slideAnimation = Tween<Offset>(
      begin: const Offset(0, -1.5),
      end: const Offset(0, 0),
    ).animate(
      CurvedAnimation(
        parent: controller as Animation<double>,
        curve: Curves.fastOutSlowIn,
      ),
    );
    opacityAnimation = Tween(begin: 0.0, end: 1.0).animate(
      CurvedAnimation(
        parent: controller as Animation<double>,
        curve: Curves.easeIn,
      ),
    );
    // _heightAnimation.addListener(() => setState(() {}));

    // passwordController = TextEditingController();
  }

  @override
  void onClose() {
    super.onClose();
    // passwordController.dispose();
  }

  bool get isAuth {
    _isAuth.value = token != null;
    return _isAuth.value;
  }

  String? get token {
    if (_expiryDate != null &&
        _expiryDate!.isAfter(DateTime.now()) &&
        _token != null) {
      return _token;
    }
    return null;
  }

  String? get userId {
    return _userId;
  }

  Future<void> _authenticate(
      String email, String password, String urlSegment) async {
    // print('app is here!!!5555');

    final host = UniversalPlatform.isAndroid ? '10.0.2.2' : '127.0.0.1';
    final url = Uri.parse('http://$host:8000/api/$urlSegment');
    //final url = Uri.parse('http://10.0.2.2:8000/api/$urlSegment');
    //final url = Uri.parse('http://127.0.0.1:8000/api/$urlSegment');

    try {
      final http.Response response = await http.post(
        url,
        headers: {"Content-Type": "application/json"},
        body: json.encode(
          {
            'email': email,
            'password': password,

            //'returnSecureToken': true,
          },
        ),
      );
      print('this is responsde ');
      print(json.decode(response.body));

      final responseData = json.decode(response.body);

      if (responseData['error'] != null) {
        throw HttpException(responseData['error']['message']);
      } else {
        _token = responseData['idToken'];
        _userId = responseData['id'];
        _expiryDate = DateTime.now().add(
          Duration(
            seconds: responseData['expiresIn'],
          ),
        );
      }
      _autoLogout();
      // update();
      final prefs = await SharedPreferences.getInstance();
      final userData = json.encode(
        {
          'token': _token,
          'userId': _userId,
          'expiryDate': _expiryDate!.toIso8601String(),
        },
      );
      prefs.setString('userData', userData);

      // print(prefs.getString('userData'));

    } catch (error) {
      throw error;
    }
  }

  Future<void> signup(String email, String password) async {
    return _authenticate(email, password, 'signup');
  }

  Future<void> login(String email, String password) async {
    return _authenticate(email, password, 'login');
  }

  Future<bool> tryAutoLogin() async {
    final prefs = await SharedPreferences.getInstance();
    if (!prefs.containsKey('userData')) {
      return false;
    }
    final Map<String, Object> extractedUserData = Map<String, Object>.from(
        json.decode(prefs.getString('userData') as String));
    final expiryDate =
        DateTime.parse(extractedUserData['expiryDate'] as String);

    if (expiryDate.isBefore(DateTime.now())) {
      return false;
    }
    _token = extractedUserData['token'] as String;
    _userId = extractedUserData['userId'] as String;
    _expiryDate = expiryDate;
    // update();
    _autoLogout();
    return true;
  }

  Future<void> logout() async {
    _token = null;
    _userId = null;
    _expiryDate = null;
    if (_authTimer != null) {
      _authTimer!.cancel();
      _authTimer = null;
    }
    // update();
    final prefs = await SharedPreferences.getInstance();
    // prefs.remove('userData');
    prefs.clear();
  }

  void _autoLogout() {
    if (_authTimer != null) {
      _authTimer!.cancel();
    }
    final timeToExpiry = _expiryDate!.difference(DateTime.now()).inSeconds;
    _authTimer = Timer(Duration(seconds: timeToExpiry), logout);
  }
}

但它仍会停留在身份验证页面上,不会转到我在main.dart 文件中定义的主页:

void main() {
  Get.put(MenuController());
  Get.put(NavigationController());
  Get.put(AuthController());
  Get.put(AuthCard);
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Obx(() => GetMaterialApp(
          initialRoute: AuthController.instance.isAuth
              ? homeScreenRoute
              : authenticationScreenRoute,
          unknownRoute: GetPage(
              name: '/not-found',
              page: () => PageNotFound(),
              transition: Transition.fadeIn),
          getPages: [
            GetPage(
                name: rootRoute,
                page: () {
                  return SiteLayout();
                }),
            GetPage(
                name: authenticationScreenRoute,
                page: () => const AuthenticationScreen()),
            GetPage(name: homeScreenRoute, page: () => const HomeScreen()),
          ],
          debugShowCheckedModeBanner: false,
          title: 'BasicCode',
          theme: ThemeData(
            scaffoldBackgroundColor: light,
            textTheme: GoogleFonts.mulishTextTheme(Theme.of(context).textTheme)
                .apply(bodyColor: Colors.black),
            pageTransitionsTheme: const PageTransitionsTheme(builders: {
              TargetPlatform.iOS: FadeUpwardsPageTransitionsBuilder(),
              TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(),
            }),
            primarySwatch: Colors.blue,
          ),
        ));
  }
}

有什么问题,我该如何解决?

【问题讨论】:

    标签: flutter token flutter-getx obs


    【解决方案1】:

    初始路由仅在应用启动时设置一次,根据您所显示的内容,isAuth 将始终在 GetMaterialApp 构建时返回 false。

    将整个应用程序包装在 Obx 中不会触发基于您为初始路线设置的导航。到您运行任何登录尝试时,它已经过去了。

    您需要在成功登录后手动导航到主屏幕。

    相反,我建议在应用程序启动之前从存储中检查非空令牌,如果它为空,请转到您的身份验证页面,如果不是,请转到您的主页。这两者都不需要Obx 围绕GetMaterialApp,因为您需要在runApp() 之前正确初始化_isAuthawait

    【讨论】:

    • 感谢您的回答。由于我是一个新学习者并且没有太多经验,您能否帮助我并给我一个示例代码或修改我现有的代码以了解我必须做什么?
    【解决方案2】:

    我可以通过在我的main.dart 文件中添加以下行来简单地解决问题:

      home: Obx(() => AuthController.instance.isAuth
          ? const HomeScreen()
          : const AuthenticationScreen()),
    

    并删除以下内容:

       initialRoute
       : AuthController.instance.isAuth
           ? homeScreenRoute
           : authenticationScreenRoute,
    

    我还删除了GetMaterialApp()之前的Obx

    新的main.dart 如下所示:

    void main() {
      Get.put(MenuController());
      Get.put(NavigationController());
      Get.put(AuthController());
      Get.put(AuthCard);
      AuthController.instance.isAuth ? runApp(MyApp()) : runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return GetMaterialApp(
          unknownRoute: GetPage(
              name: '/not-found',
              page: () => PageNotFound(),
              transition: Transition.fadeIn),
          getPages: [
            GetPage(
                name: rootRoute,
                page: () {
                  return SiteLayout();
                }),
            GetPage(
                name: authenticationScreenRoute,
                page: () => const AuthenticationScreen()),
            GetPage(name: homeScreenRoute, page: () => const HomeScreen()),
          ],
          debugShowCheckedModeBanner: false,
          title: 'BasicCode',
          theme: ThemeData(
            scaffoldBackgroundColor: light,
            textTheme: GoogleFonts.mulishTextTheme(Theme.of(context).textTheme)
                .apply(bodyColor: Colors.black),
            pageTransitionsTheme: const PageTransitionsTheme(builders: {
              TargetPlatform.iOS: FadeUpwardsPageTransitionsBuilder(),
              TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(),
            }),
            primarySwatch: Colors.blue,
          ),
          home: Obx(() => AuthController.instance.isAuth
              ? const HomeScreen()
              : const AuthenticationScreen()),
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-03-15
      • 1970-01-01
      • 1970-01-01
      • 2021-09-19
      • 1970-01-01
      • 2021-12-20
      • 2023-02-15
      • 1970-01-01
      • 2021-12-10
      相关资源
      最近更新 更多