簡體   English   中英

為什么我的可觀察變量無法使用 GetX 更新 Flutter 中的“main.dart”?

[英]Why my observable variable can not update the "main.dart" in Flutter using GetX?

以下代碼是我的auth_controller.dart代碼。 我看到response來自后端工作,這是預期的,我有token ,並且在我提交表單后isAuth值更改為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);
  }
}

但它仍然會堅持身份驗證頁面,並且不會 go 到我在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,
          ),
        ));
  }
}

有什么問題,我該如何解決?

初始路由僅在應用程序啟動時設置一次,並且根據您顯示的內容, isAuth將始終在GetMaterialApp構建時返回 false。

將整個應用程序包裝在Obx中不會觸發基於您為初始路線設置的導航。 當您運行任何登錄嘗試時,它已經過去了。

成功登錄后,您需要手動導航到主屏幕。

Instead I suggest checking for a non null token from storage before the app starts and if its null, go to your auth page and if not, go to your home page. 兩者都不需要Obx周圍的GetMaterialApp ,因為您需要正確初始化_isAuth並在runApp()之前await它。

我可以通過在我的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()),
    );
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM