Flutter 根据对提供值的更改更改UI
我有一个屏幕,如果提供的布尔值(isLoggedIn)更改为true,我希望从该屏幕导航到新屏幕。下面的第一个生成方法不可能,因为在生成过程中无法调用Navigator。我试图在构建中这样做,因为我需要访问上下文才能使用我的提供程序。来自授权提供者的isLoggedIn的值可能随时发生变化,因此我必须对此进行检查 如何使用提供程序和导航器解决此问题Flutter 根据对提供值的更改更改UI,flutter,flutter-provider,flutter-navigation,Flutter,Flutter Provider,Flutter Navigation,我有一个屏幕,如果提供的布尔值(isLoggedIn)更改为true,我希望从该屏幕导航到新屏幕。下面的第一个生成方法不可能,因为在生成过程中无法调用Navigator。我试图在构建中这样做,因为我需要访问上下文才能使用我的提供程序。来自授权提供者的isLoggedIn的值可能随时发生变化,因此我必须对此进行检查 如何使用提供程序和导航器解决此问题 //Not working solution Widget build(BuildContext context) { Authorizatio
//Not working solution
Widget build(BuildContext context) {
Authorization auth = Provider.of<Authorization>(context);
return Scaffold(
body: Center(
child: auth.isLoggedIn
? Text(
"Logged In",
)
: Navigator.pushReplacementNamed(context, 'sign-in')),
);
}
//解决方案不起作用
小部件构建(构建上下文){
授权授权=提供者(上下文);
返回脚手架(
正文:中(
子项:auth.isLoggedIn
?文本(
“登录”,
)
:Navigator.pushReplacementNamed(上下文“登录”),
);
}
我可以在没有导航器的情况下这样做:
//Working solution
class SplashScreen extends StatelessWidget {
static const routeName = 'splash';
@override
Widget build(BuildContext context) {
final auth = Provider.of<Authorization>(context);
return auth.isLoggedIn ? HomeScreen() : SignInScreen();
}
}
//工作解决方案
类SplashScreen扩展了无状态小部件{
静态常量routeName='splash';
@凌驾
小部件构建(构建上下文){
最终认证=提供者(上下文);
返回auth.isLoggedIn?主屏幕():符号屏幕();
}
}
但我现在不知道这是否是一个可靠的方法。这里有一个解决您问题的方法
enum AuthStatus {
NOT_DETERMINED,
NOT_LOGGED_IN,
LOGGED_IN,
}//Always define this outside the class.
AuthStatus authStatus = AuthStatus.NOT_DETERMINED;
@override
void initState() {
super.initState();
getCurrentUser().then((user) {
setState(() {
if (user != null) {
_userId = user?.uid;
}
authStatus =
user?.uid == null ? AuthStatus.NOT_LOGGED_IN : AuthStatus.LOGGED_IN;
});
});
}
Future<FirebaseUser> getCurrentUser() async {
FirebaseUser user = await _firebaseAuth.currentUser();
return user;
}
void loginCallback() {
getCurrentUser().then((user) {
setState(() {
_userId = user.uid.toString();
authStatus = AuthStatus.LOGGED_IN;
Navigator.of(context).pushReplacementNamed('/');
});
});
}
Widget buildWaitingScreen() {
return Scaffold(
body: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: CircleAvatar(
backgroundColor: Colors.transparent,
radius: 70.0,
child: Image.asset('assets/icons/icon.png'),
),
),
);
}
@override
Widget build(BuildContext context) {
switch (authStatus) {
case AuthStatus.NOT_DETERMINED:
return buildWaitingScreen();
break;
case AuthStatus.NOT_LOGGED_IN:
return new LoginSignUpPage();
break;
case AuthStatus.LOGGED_IN:
if (_userId.length > 0 && _userId != null) {
return new HomePage();
} else
return buildWaitingScreen();
break;
default:
return buildWaitingScreen();
}
}
}
您正在将UI代码与功能代码混合。你不能这样做。if应该在build方法之外。您应该检查用户是否已登录,然后导航到另一个视图,或者如果用户未登录,则导航到登录页面。我知道我必须在生成方法之外删除导航器,正如我在问题中所述。由于我不知道提供的值何时更改,您将在何处进行此检查?使用navigator不是推荐的方法。我是否应该根据所提供的auth boolean中的更改返回所需的屏幕@Jo.Sang-O SoaRes你不认为这是UI代码和功能代码的混合吗?这里仍然在检查构建方法中的值吗?这只是方法的一个例子。这是为了帮助您保持用户登录。这样,如果你关闭应用程序,你就不必再次登录。还有另一个选项:如果登录,则可以在initState中调用代码中的loginCallback()来导航用户,否则将生成主上下文好的,在我的情况下,依赖BuildContext从提供程序获取身份验证,我无法在initState中执行此操作。此外,在您的情况下,initState可以检查AuthStatus的动态更改吗?还是只有在调用initState时才开始检查?
void loginCallback() {
getCurrentUser().then((user) {
setState(() {
_userId = user.uid.toString();
authStatus = AuthStatus.LOGGED_IN;
});});
if(authStatus==AuthStatus.LOGGED_IN){
Navigator.pushReplacementNamed(context, 'sign-in')} }