【问题标题】:Flutter Auth State not changing in Wrapper() when (user == null) => WelcomeScreen()当(user == null)=> WelcomeScreen()时,Wrapper()中的颤振身份验证状态没有改变
【发布时间】:2021-07-11 11:47:50
【问题描述】:

当我编写 if(user == null) => LoginScreen() 时,屏幕会显示我的登录屏幕,我需要按下登录按钮,这样屏幕才会显示主屏幕 MainScreen()。好消息,这真的很有效。

但我需要用户首先进入欢迎屏幕(当 user == null 时)所以我将 Wrapper() 中的代码从 if(user==null){LoginScreen()} 更改为 if(user= =null){欢迎页面()}。在欢迎屏幕中,如果用户按下登录按钮,用户将被导航到登录页面 (LoginScreen()),然后注册到 RegisterScreen()。

这是 if (if(user == null)=> WelcomeScreen();) 的路径:

WelcomeSceen() => LoginScreen() => MainScreen()

所以问题发生在屏幕显示 WelcomePage() 时,我按下登录按钮导航到 LoginScreen(),然后按下登录按钮(这样我可以导航到 MainScreen())。屏幕没有将我重定向到 MainScreen(),但我的终端中有“用户已登录”(基于我在包装器中编码的内容)。之后我重新启动应用程序时,屏幕会将我重定向到主屏幕。

真的需要知道为什么会发生这种情况,以及如何解决这个问题,这样我仍然可以先向用户显示 WelcomeScreen。

下面是我的代码和目录。

main.dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:uberclone/models/usermodel.dart';
import 'package:uberclone/services/auth.dart';
import 'package:uberclone/wrapper.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  Firebase.initializeApp();
  runApp(App());
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamProvider<UserModel?>.value(
      value: AuthService().user,
      initialData: null,
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Wrapper(),
      ),
    );
  }
} 

wrapper.dart更改前

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:uberclone/models/usermodel.dart';
import 'package:uberclone/screens/authentication/loginscreen.dart';
import 'package:uberclone/screens/home/mainscreen.dart';

class Wrapper extends StatefulWidget {
  @override
  _WrapperState createState() => _WrapperState();
}

class _WrapperState extends State<Wrapper> {
  @override
  Widget build(BuildContext context) {
    final user = Provider.of<UserModel?>(context);
    print(user);
    if (user == null) {
      return LoginScreen();
    } else {
      return MainScreen();
    }
  }
}

wrapper.dart更改后

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:uberclone/models/usermodel.dart';
import 'package:uberclone/screens/authentication/welcomescreen.dart';
import 'package:uberclone/screens/home/mainscreen.dart';

class Wrapper extends StatefulWidget {
  @override
  _WrapperState createState() => _WrapperState();
}

class _WrapperState extends State<Wrapper> {
  @override
  Widget build(BuildContext context) {
    final user = Provider.of<UserModel?>(context);
    print(user);
    if (user == null) {
      return WelcomeScreen();
    } else {
      return MainScreen();
    }
  }
}

auth.dart

import 'package:firebase_auth/firebase_auth.dart';
import 'package:uberclone/models/usermodel.dart';

class AuthService {
  final FirebaseAuth _auth = FirebaseAuth.instance;

  UserModel? _userFromFirebaseUser(User? user) {
    return user != null ? UserModel(uid: user.uid) : null;
  }

  Stream<UserModel?> get user {
    return _auth.authStateChanges().map(_userFromFirebaseUser);
  }

  Future signInAnon() async {
    try {
      UserCredential result = await _auth.signInAnonymously();
      User? user = result.user;
      return _userFromFirebaseUser(user);
    } catch (e) {
      print(e.toString());
      return null;
    }
  }

  Future signOut() async {
    try {
      await _auth.signOut();
    } catch (e) {
      print(e.toString());
      return null;
    }
  }
}

loginscreen.dart

import 'package:flutter/material.dart';
import 'package:uberclone/screens/authentication/registerscreen.dart';
import 'package:uberclone/screens/authentication/welcomescreen.dart';
import 'package:uberclone/services/auth.dart';

class LoginScreen extends StatefulWidget {
  static const String idScreen = 'loginscreen';
  @override
  _LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  final AuthService _auth = AuthService();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 0,
        backgroundColor: Colors.white,
        leading: IconButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => WelcomeScreen()),
            );
          },
          icon: Icon(Icons.arrow_back_rounded),
          color: Colors.black,
        ),
      ),
      body: SingleChildScrollView(
        child: Container(
          padding: EdgeInsets.symmetric(horizontal: 20, vertical: 5),
          child: Column(
            children: [
              Container(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.start,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Text(
                      'Please sign in',
                      style: TextStyle(
                          fontSize: 25,
                          fontWeight: FontWeight.normal,
                          color: Colors.black),
                    ),
                    SizedBox(height: 20),
                    Container(
                      height: 50,
                      color: Colors.grey[200],
                      padding:
                          EdgeInsets.symmetric(horizontal: 10, vertical: 3),
                      child: TextField(
                        style: TextStyle(fontSize: 20),
                        decoration: InputDecoration(
                          border: InputBorder.none,
                          hintText: 'Email Address',
                        ),
                      ),
                    ),
                    SizedBox(height: 15),
                    Container(
                      height: 50,
                      color: Colors.grey[200],
                      padding:
                          EdgeInsets.symmetric(horizontal: 10, vertical: 3),
                      child: TextField(
                        style: TextStyle(fontSize: 20),
                        obscureText: true,
                        decoration: InputDecoration(
                          border: InputBorder.none,
                          hintText: 'Password',
                        ),
                      ),
                    ),
                    SizedBox(height: 2),
                    TextButton(
                        onPressed: () {
                          Navigator.push(
                            context,
                            MaterialPageRoute(
                                builder: (context) => RegisterScreen()),
                          );
                        },
                        child: Text(
                          'Dont have any Veko Driver account? Register here',
                          style:
                              TextStyle(color: Color(0xff0466c8), fontSize: 15),
                        ))
                  ],
                ),
              ),
              Container(
                padding: EdgeInsets.only(top: 320),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: <Widget>[
                    MaterialButton(
                      height: 55,
                      onPressed: () async {
                        dynamic result = await _auth.signInAnon();
                        if (result == null) {
                          print('user has not signed in');
                        } else {
                          print('user has signed in');
                          print(result.uid);
                        }
                      },
                      elevation: 0,
                      color: Colors.black,
                      child: Text(
                        'Log in',
                        style: TextStyle(color: Colors.white, fontSize: 22),
                      ),
                    )
                  ],
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

welcomescreen.dart

import 'package:flutter/material.dart';
import 'package:uberclone/screens/authentication/loginscreen.dart';
import 'package:uberclone/screens/authentication/registerscreen.dart';
import 'package:uberclone/screens/authentication/safetyscreen.dart';

class WelcomeScreen extends StatefulWidget {
  static const String idScreen = 'welcomescreen';
  @override
  _WelcomeScreenState createState() => _WelcomeScreenState();
}

class _WelcomeScreenState extends State<WelcomeScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: Column(
          children: <Widget>[
            Container(
                child: Image.asset('assets/images/veko-rider-coverpage7.jpg')),
            Container(
              padding: EdgeInsets.only(left: 20, right: 20, top: 15, bottom: 5),
              child: Column(
                children: <Widget>[
                  Align(
                    alignment: Alignment.topLeft,
                    child: Text(
                      'Welcome to the Veko',
                      style: TextStyle(
                          fontSize: 22,
                          color: Colors.black,
                          fontWeight: FontWeight.bold),
                    ),
                  ),
                  Align(
                    alignment: Alignment.bottomLeft,
                    child: Text(
                      'Driver app',
                      style: TextStyle(
                          fontSize: 22,
                          color: Colors.black,
                          fontWeight: FontWeight.bold),
                    ),
                  ),
                  SizedBox(height: 15),
                  Container(
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        MaterialButton(
                          onPressed: () {
                            Navigator.push(
                              context,
                              MaterialPageRoute(
                                  builder: (context) => LoginScreen()),
                            );
                          },
                          elevation: 0,
                          color: Colors.black,
                          height: 40,
                          child: Padding(
                            padding: EdgeInsets.symmetric(
                                horizontal: 40, vertical: 10),
                            child: Text(
                              'Sign in',
                              style:
                                  TextStyle(color: Colors.white, fontSize: 18),
                            ),
                          ),
                        ),
                        SizedBox(width: 10),
                        MaterialButton(
                          onPressed: () {
                            Navigator.push(
                              context,
                              MaterialPageRoute(
                                  builder: (context) => RegisterScreen()),
                            );
                          },
                          elevation: 0,
                          color: Colors.grey[200],
                          height: 40,
                          child: Padding(
                            padding: EdgeInsets.symmetric(
                                horizontal: 38, vertical: 10),
                            child: Text(
                              'Register',
                              style:
                                  TextStyle(color: Colors.black, fontSize: 18),
                            ),
                          ),
                        )
                      ],
                    ),
                  ),
                ],
              ),
            ),
            Divider(
              color: Colors.grey[400],
            ),
            Container(
              padding: EdgeInsets.symmetric(horizontal: 15),
              child: Row(
                children: [
                  MaterialButton(
                      padding: EdgeInsets.symmetric(horizontal: 3, vertical: 5),
                      onPressed: () {
                        Navigator.pushNamedAndRemoveUntil(
                            context, SafetyScreen.idScreen, (route) => false);
                      },
                      child: Icon(Icons.arrow_back_rounded)),
                  SizedBox(width: 8),
                  TextButton(
                      onPressed: () {},
                      child: Align(
                        alignment: Alignment.centerRight,
                        child: Text(
                          'or Ride with Veko',
                          style: TextStyle(fontSize: 18),
                        ),
                      )),
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}

【问题讨论】:

标签: firebase flutter authentication firebase-authentication


【解决方案1】:

希望您到目前为止解决了您的问题, 我是一个颤抖的新手,实际上我遇到了同样的问题并且没有找到合适的解决方案......而且这个线程似乎是一个死胡同。所以我想把这个答案留给其他人,尽管你在 9 个月前问过这个问题。

问题是您已经导航到小部件树中的另一个页面。

例如,当用户要登录时,最初您的小部件树(导航堆栈)如下:

WelcomeScreen() => LoginScreen()

当用户输入他的凭据并按下登录时,更改确实发生了,小部件树如下所示:

MainScreen() => LoginScreen()

为了简化...更改确实发生了,但您已经站在登录屏幕上(即登录屏幕位于导航堆栈的顶部,主屏幕的更改发生在导航堆栈的一个位置) .

对于它的解决方案,(在我的情况下,至少因为我也想要动画)我在 WelcomeScreen 和 LoginScreen 之间使用了一个动画切换器(所以理论上我的导航堆栈将始终包含 1 页)。

另一个解决方案(糟糕但没问题)是您可以将 Wrapper 用于 LoginScreen 和 MainScreen 而不是 WelcomeScreen 和 MainScreen,因此它始终是被替换的首页......但这个解决方案的问题是每次你都会热重载时,WelcomeScreen 肯定会显示,直到您导航到 LoginScreen(这是做出决定的地方,您将看到相应的屏幕)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-15
    • 2022-01-04
    • 2021-03-04
    • 1970-01-01
    • 1970-01-01
    • 2021-03-22
    相关资源
    最近更新 更多