[英]Why my observable variable can not update the "main.dart" in Flutter using GetX?
The following code is my auth_controller.dart
code.以下代码是我的
auth_controller.dart
代码。 I see the response
comes from the backend works and it is what was expected and I have token
and the isAuth
value changes to true
after I submit the form:我看到
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);
}
}
But it will still sticks to the Authentication page and won't go to the Home page as I defined in my main.dart
file:但它仍然会坚持身份验证页面,并且不会 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,
),
));
}
}
What is the problem and how can I fix that?有什么问题,我该如何解决?
Initial route is set only once when the app starts, and based on what you've shown isAuth
will always return false by the time GetMaterialApp
is built.初始路由仅在应用程序启动时设置一次,并且根据您显示的内容,
isAuth
将始终在GetMaterialApp
构建时返回 false。
Wrapping your whole app in an Obx
is not going to trigger a navigation based on what you have set for the initial route.将整个应用程序包装在
Obx
中不会触发基于您为初始路线设置的导航。 Its way past that by the time you've run any login attempt.当您运行任何登录尝试时,它已经过去了。
You need to manually navigate to home screen after a successful login.成功登录后,您需要手动导航到主屏幕。
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. 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. Neither of which would require an
Obx
around GetMaterialApp
because you need to properly initialize _isAuth
and await
it before runApp()
.两者都不需要
Obx
周围的GetMaterialApp
,因为您需要正确初始化_isAuth
并在runApp()
之前await
它。
I could simply resolve the problem by adding following lines to my main.dart
file:我可以通过在我的
main.dart
文件中添加以下行来简单地解决问题:
home: Obx(() => AuthController.instance.isAuth
? const HomeScreen()
: const AuthenticationScreen()),
And removing the followings:并删除以下内容:
initialRoute
: AuthController.instance.isAuth
? homeScreenRoute
: authenticationScreenRoute,
I also deleted the Obx
before the GetMaterialApp()
.我还在
GetMaterialApp()
之前删除了Obx
。
The new main.dart
looks like this:新的
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.