【问题标题】:How to replace "notifyListeners()" with "update()" using GetX in Flutter?如何在 Flutter 中使用 GetX 将“notifyListeners()”替换为“update()”?
【发布时间】:2022-01-13 01:48:01
【问题描述】:

我正在尝试修改以下使用有状态小部件和提供程序包的代码,以改用 GetX 包和无状态小部件。在部分代码中,它指定用户是否通过身份验证以显示homeauth 屏幕。这是auth_controller.dart 代码:

class Auth with ChangeNotifier {
  String? _token;
  DateTime? _expiryDate;
  String? _userId;
  Timer? _authTimer;

  bool get isAuth {
    return token != null;
  }

  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 {
    final host = Platform.isAndroid ? '10.0.2.2' : '127.0.0.1';

    final url = Uri.parse('http://$host:8080/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,
          },
        ),
      );

      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();
      notifyListeners();
      final prefs = await SharedPreferences.getInstance();
      final userData = json.encode(
        {
          'token': _token,
          'userId': _userId,
          'expiryDate': _expiryDate!.toIso8601String(),
        },
      );

      prefs.setString('userData', userData);
    } catch (error) {
      throw error;
    }
  }

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

  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;
    notifyListeners();
    _autoLogout();
    return true;
  }

  Future<void> logout() async {
    _token = null;
    _userId = null;
    _expiryDate = null;
    if (_authTimer != null) {
      _authTimer!.cancel();
      _authTimer = null;
    }
    notifyListeners();
    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() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider.value(
          value: Auth(),
        ),
      ],
      child: Consumer<Auth>(
        builder: (ctx, auth, _) => MaterialApp(
          title: 'MyShop',
          theme: ThemeData(
            primarySwatch: Colors.purple,
            accentColor: Colors.deepOrange,
            fontFamily: 'Lato',
          ),
          home: auth.isAuth
              ? MainScreen()
              : FutureBuilder(
                  future: auth.tryAutoLogin(),
                  builder: (ctx, authResultSnapshot) =>
                      authResultSnapshot.connectionState ==
                              ConnectionState.waiting
                          ? SplashScreen()
                          : AuthScreen(),
                ),
          routes: {
            MainScreen.routeName: (ctx) => const MainScreen(),
            UserAccountScreen.routeName: (ctx) => const UserAccountScreen(),

          },
        ),
      ),
    );
  }

我尝试更改类以扩展GetXController,还通过在它们的末尾添加.obs 并通过将侦听器部分包装在Obx 中来侦听它们的更改,从而使某些变量成为可观察的。但我不知道我应该如何处理isAuth 变量?看来我修改后的新代码无法更新isAuth状态,它始终为`false,这使身份验证页面始终处于打开状态,并且无法进入用户应用程序。

编辑:这是修改后的main.dart

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return 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: () => 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: AuthenticationPage(),
    );
  }
}

【问题讨论】:

    标签: flutter observable listener state-management flutter-getx


    【解决方案1】:

    您可以使用 GetBuilder() 包装您的无状态小部件,如下所示:

    GetBuilder<YourController>(
          id: 'id_name',
         builder: (controller) {
       if (controller.isAuth) {
          return OneWidget();
       } else {
          return SecondWidget();
       }
    }
    

    更改 isAuth 的值后是否需要使用 update(['id_name']),这会生成 GetBuilder 的重建。

    【讨论】:

    • 谢谢。 1. 什么是id,它来自哪里? 2. 我尝试了类似于您在main.dart 中建议的方法,但没有奏效。您可以编辑我放置的main.dart 代码以显示我应该如何做吗?
    • 我还在编辑部分添加了我修改后的main.dart 代码。
    猜你喜欢
    • 2021-03-06
    • 2021-11-11
    • 2021-06-07
    • 2021-07-06
    • 1970-01-01
    • 2022-12-14
    • 2022-10-25
    • 1970-01-01
    • 2021-05-03
    相关资源
    最近更新 更多