成功登录后,我的登录屏幕没有将我重定向到新屏幕!扑

时间:2021-02-11 20:26:06

标签: android firebase flutter google-cloud-firestore firebase-authentication

大家好,我在 flutter 中遇到了一个奇怪的错误,当我尝试登录时,它不会将我重定向到我的经过身份验证的页面(状态不会更新),但它保持原样,它只会重定向我在我热重启应用程序后。 以前它运行良好,但现在我不知道我的代码有什么问题,如果您能指出我的错误,那将对我大有帮助。 提前致谢

main.dart

import 'package:flutter/services.dart';
import 'package:flutter/material.dart';

import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:provider/provider.dart';

import './providers/user_provider.dart';
import './screens/tab_bar_screen.dart';
import './screens/auth/auth_tab_bar_screen.dart';
import './screens/login_screen.dart';
import './screens/auth/admin/edit_project_screen.dart';
import './screens/auth/admin/register_user.dart';
import './screens/auth/project_detail_screen.dart';
import './providers/auth.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        Provider<Auth>(
          create: (_) => Auth(FirebaseAuth.instance),
        ),
        StreamProvider(
          create: (context) =>
              Provider.of<Auth>(context, listen: false).authStateChanges,
        ),
      ],
      child: MaterialApp(
        theme: ThemeData(
          primaryColor: Colors.blue,
          backgroundColor: Colors.blue,
          accentColor: Colors.blueAccent,
          brightness: Brightness.light,
          accentColorBrightness: Brightness.light,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        debugShowCheckedModeBanner: false,
        home: AuthenticationWrapper(),
        routes: {
          LoginScreen.routeName: (ctx) => LoginScreen(),
          TabBarScreen.routeName: (ctx) => TabBarScreen(),
          AuthTabBarScreen.routeName: (ctx) => AuthTabBarScreen(),
          EditProjectScreen.routeName: (ctx) => EditProjectScreen(),
          RegisterUserScreen.routeName: (ctx) => RegisterUserScreen(),
          ProjectDetailScreen.routeName: (ctx) => ProjectDetailScreen(),
        },
      ),
    );
  }
}

class AuthenticationWrapper extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final _firebaseUser = context.watch<User>();

    if (_firebaseUser != null) {
      return AuthTabBarScreen();
    } else {
      return TabBarScreen();
    }
  }
}

auth.dart

import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

class Auth {
  final FirebaseAuth _firebaseAuth;
  Auth(this._firebaseAuth);

  final databaseReference = FirebaseFirestore.instance;

  Stream<User> get authStateChanges => _firebaseAuth.authStateChanges();

  //Get Current User UID
  Future<String> userUid() async {
    return _firebaseAuth.currentUser.uid;
  }

  //Get Current User
  Future<void> getCurrentUser() async {
    return _firebaseAuth.currentUser;
  }

  Future<String> login(
    String email,
    String password,
  ) async {
    try {
      await _firebaseAuth.signInWithEmailAndPassword(
          email: email, password: password);
      return 'Signed in';
    } on FirebaseAuthException catch (error) {
      print(error.message);
      return error.message;
    }
  }

  Future<void> signUp(
    String email,
    String password,
    String firstName,
    String lastName,
    bool isAdmin,
  ) async {
    try {
      // Create a new user
      final currentUser = await _firebaseAuth.createUserWithEmailAndPassword(
          email: email, password: password);

      // Update user
      await databaseReference
          .collection("users")
          .doc(currentUser.user.uid)
          .set({
        'firstName': firstName,
        'lastName': lastName,
        'email': currentUser.user.email,
        'isAdmin': isAdmin,
      });
    } on FirebaseAuthException catch (error) {
      return error.message;
    }
  }

  Future<void> logout() async {
    await _firebaseAuth.signOut();
  }
}

login_screen.dart

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../providers/auth.dart';

class LoginScreen extends StatefulWidget {
  static const routeName = '/login';

  @override
  _LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  final _passwordFocusNode = FocusNode();
  final _passwordController = TextEditingController();

  var _isLoading = false;

  final _formKey = GlobalKey<FormState>();

  Map<String, String> _authData = {
    'email': '',
    'password': '',
  };

  void _showErrorDialogBox(String message) async {
    return showDialog(
      context: context,
      builder: (ctx) => AlertDialog(
        title: Text('An error occurred'),
        content: Text(message),
        actions: <Widget>[
          FlatButton(
            onPressed: () {
              Navigator.of(ctx).pop();
            },
            child: Text('Okay'),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    _passwordFocusNode.dispose();
    _passwordController.dispose();
    super.dispose();
  }

  Future<void> _submit() async {
    if (!_formKey.currentState.validate()) {
      // Invalid!
      return;
    }
    _formKey.currentState.save();
    setState(() {
      _isLoading = true;
    });
    try {
      await Provider.of<Auth>(context, listen: false).login(
        _authData['email'],
        _authData['password'],
      );
    } on FirebaseAuthException catch (error) {
      return error.message;
    } catch (error) {
      const errorMessage = 'Authentication failed, please try again later.';
      _showErrorDialogBox(errorMessage);
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Login'),
        centerTitle: true,
      ),
      body: Padding(
        padding: const EdgeInsets.all(25),
        child: Form(
          key: _formKey,
          child: SingleChildScrollView(
            child: Column(
              children: <Widget>[
                Container(
                  padding: EdgeInsets.only(top: 30, bottom: 30),
                  child: Image.asset('assets/images/logo.png'),
                ),
                TextFormField(
                  decoration: InputDecoration(
                    labelText: 'E-Mail',
                    border: OutlineInputBorder(
                      borderSide:
                          BorderSide(color: Theme.of(context).primaryColor),
                    ),
                    hintText: 'Type your email address',
                    hintStyle: TextStyle(
                      fontSize: 12,
                    ),
                  ),
                  keyboardType: TextInputType.emailAddress,
                  textInputAction: TextInputAction.next,
                  focusNode: _passwordFocusNode,
                  validator: (value) {
                    Pattern pattern =
                        r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
                    RegExp regex = new RegExp(pattern);
                    if (!regex.hasMatch(value))
                      return 'Enter a Valid Email';
                    else
                      return null;
                  },
                  onSaved: (value) {
                    _authData['email'] = value;
                  },
                ),
                SizedBox(
                  height: 35,
                ),
                TextFormField(
                  decoration: InputDecoration(
                    labelText: 'Password',
                    border: OutlineInputBorder(
                      borderSide:
                          BorderSide(color: Theme.of(context).primaryColor),
                    ),
                    hintText: 'Type your password',
                    hintStyle: TextStyle(
                      fontSize: 12,
                    ),
                  ),
                  obscureText: true,
                  textInputAction: TextInputAction.done,
                  //controller: _passwordController,
                  validator: (value) {
                    if (value.isEmpty || value.length <= 5) {
                      return 'Password is too short!';
                    }
                    return null;
                  },
                  onSaved: (value) {
                    _authData['password'] = value;
                  },
                ),
                SizedBox(
                  height: 35,
                ),
                if (_isLoading)
                  CircularProgressIndicator()
                else
                  RaisedButton(
                    color: Theme.of(context).primaryColor,
                    onPressed: _submit,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(5),
                    ),
                    child: Text(
                      'LOGIN',
                      style: TextStyle(
                        color: Colors.white,
                      ),
                    ),
                  ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

1 个答案:

答案 0 :(得分:1)

好吧,伙计们,我发现了问题所在,我在问题上发布的代码确实是正确的,问题在于我退出的方式

之前的代码:

    // EF core test
    [Test] // failed
    public void Test1()
    {
        var options = new DbContextOptionsBuilder<ConsoleApp1.Context>()
            .UseInMemoryDatabase(databaseName: "Data")
            .ConfigureWarnings(x => x.Ignore(InMemoryEventId.TransactionIgnoredWarning))
            .Options;

        var context = new ConsoleApp1.Context(options);
        context.Books.Add(new ConsoleApp1.Book { Id = -1 });
        context.Books.Add(new ConsoleApp1.Book { Id = 0 });
        context.Books.Add(new ConsoleApp1.Book { Id = -1 });

        Assert.Pass();
    }

    // EF 6 test
    [Test] // passed
    public void Test2()
    {
        var context = new ConsoleApp2.Context();
        context.Books.Add(new ConsoleApp2.Book { Id = -1 });
        context.Books.Add(new ConsoleApp2.Book { Id = 0 });
        context.Books.Add(new ConsoleApp2.Book { Id = -1 });

        Assert.Pass();
    }

固定代码:

ListTile(
              leading: Icon(Icons.logout),
              title: Text('Logout'),
              onTap: () {
                Navigator.of(context).pop();
                Navigator.of(context)
                    .pushReplacementNamed(TabBarScreen.routeName);
                Provider.of<Auth>(context, listen: false).logout();
              },
            )

这是因为firebase已经处理了ListTile( leading: Icon(Icons.logout), title: Text('Logout'), onTap: () { Provider.of<Auth>(context, listen: false).logout(); }, ) pop()push()(我在main.dart中给出的),当我手动尝试时出现了冲突到 homepage() 并替换页面并将用户重定向到 pop()

希望这是一个足够好的解释。