问题描述
我目前被困在我希望是一个简单的问题上,我只是尝试了很多,以至于我可能再也看不到解决方案了。
我有一个登陆页面,通过未来检查用户是否有活动会话(解析后端)。 我设法提出成功的登录和注册请求,只是屏幕没有改变,这意味着未来的构建器不会重建。当我热重载时一切正常,但我无法自动触发热重载。我使用 Riverpod 进行状态管理。 hasUserLogged() 方法由 AuthBase 类通过 Riverpod 提供。 我将 updatedUser 方法交给 AuthScreen 以在登录/注册时触发它,但它不会触发 FutureBuilder 的重建。 我认为从服务器获取 updatedUser 还会在下一步中为我提供用户是否验证了其电子邮件的信息,但这是后续问题(但我希望能在正确的方向上指出如何解决 4x4 用户矩阵:有令牌/无令牌和已验证/未验证的电子邮件并根据组合重定向到身份验证/验证电子邮件/主页..)
无论如何,现在 - 如何在 AuthScreen 中按下登录/注册按钮时触发 FutureBuilder 的重建?
class LandingPage2 extends StatefulWidget {
@override
_LandingPage2State createState() => _LandingPage2State();
}
class _LandingPage2State extends State<LandingPage2> {
Future<ParseUser> _updateUser() async {
final auth = context.read(authProvider);
ParseUser currentUser = await ParseUser.currentUser() as ParseUser;
if (currentUser != null) {
ParseResponse update = await currentUser.getUpdatedUser();
if (update.success) {
currentUser = update.result as ParseUser;
await auth.hasUserLogged();
setState(() {
return currentUser;
});
}
}
if (currentUser == null) {
print('null User');
}
}
/// Check if user session token is valid
Future<bool> hasUserLogged() async {
ParseUser currentUser = await ParseUser.currentUser() as ParseUser;
// return false if no user is logged in
if (currentUser == null) {
return false;
}
//Validates that the user's session token is valid
final ParseResponse parseResponse =
await ParseUser.getCurrentUserFromServer(
currentUser.get<String>('sessionToken'));
if (!parseResponse.success) {
print('invalid session. logout');
//Invalid session. logout
await currentUser.logout();
return false;
} else {
print('login successfull');
return true;
}
}
@override
Widget build(BuildContext context) {
final auth = context.read(authProvider);
return FutureBuilder<bool>(
future: auth.hasUserLogged(),builder: (context,snapshot) {
print('futurebuilder rebuild');
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return SplashScreen();
break;
default:
if (snapshot.hasData && snapshot.data) {
return HomePage();
} else {
return AuthScreen(_updateUser);
}
}
},);
}
}
非常感谢任何帮助,几个小时以来一直在挣扎,我的头脑无法理解为什么它不起作用:-/
解决方法
谢谢@Randal Schwartz,在我创建了一个 AuthNotifier 和 StateNotifierProvider 来管理用户状态并在 hasUserLogged() 方法中依赖该用户之后,'watch' 让它发生了。
如果有人也在挣扎 - 这就是工作版本:
import 'dart:async';
import 'package:app/screens/splash_screen.dart';
import 'package:app/services/top_level_providers.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';
import 'auth_screen.dart';
import 'home.dart';
class LandingPage2 extends ConsumerWidget {
@override
Widget build(BuildContext context,ScopedReader watch) {
final auth = watch(authProvider);
/// Check if user session token is valid
Future<bool> hasUserLogged() async {
print('hasUserLogged - Fired');
/// watch current User state -- Triggers rebuild after login!
final authNotifier = watch(authNotifierProvider.state);
final ParseUser currentUser = authNotifier;
// return false if no user is logged in
if (currentUser == null) {
print('currentUserNULL');
return false;
}
//Validates that the user's session token is valid
final ParseResponse parseResponse =
await ParseUser.getCurrentUserFromServer(
currentUser.get<String>('sessionToken'));
if (!parseResponse.success) {
print('invalid session. logout');
//Invalid session. Logout
await currentUser.logout();
return false;
} else {
print('login successfull');
return true;
}
}
return FutureBuilder<bool>(
future: hasUserLogged(),builder: (context,snapshot) {
print('futurebuilder rebuild');
// print(snapshot.data);
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return SplashScreen();
break;
default:
if (snapshot.hasData && snapshot.data) {
/// Add Verify E-Mail Logic here - Another Future Builder??
return HomePage();
} else {
// _updateUser();
return AuthScreen();
}
break;
}
},);
}
}
身份验证通知程序:
/// Auth Notifier Class
class AuthNotifier extends StateNotifier<ParseUser> {
AuthNotifier(ParseUser state) : super(state);
setCurrentUser(ParseUser user) {
state = user;
}
void clearUser() {
state = null;
}
}
和提供者:
final authNotifierProvider = StateNotifierProvider((ref) {
return AuthNotifier(null);
});
这是在收到登录/注册后的活动用户后触发的,从而触发 hasUserLogged 的重建。
authNotifier.setCurrentUser(user);
感谢您的帮助!确实花了我很多时间...不得不从 firebase 切换掉...