在颤动中将登录的用户存储到云 Firestore

Posted

技术标签:

【中文标题】在颤动中将登录的用户存储到云 Firestore【英文标题】:Store logged in users to cloud Firestore in flutter 【发布时间】:2021-02-04 04:17:09 【问题描述】:

在我的 Flutter 应用中,用户使用手机登录。那么如何将用户 ID 存储在云 Firestore 中并保存帐户以供用户再次登录并保留其详细信息? (我使用共享偏好来检查用户是否已登录)

如果需要,这是我的代码。

import 'package:country_code_picker/country_code_picker.dart';
import 'package:demo/Firebase/auth.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

import 'BottomBarPages/home.dart';

class SignIn extends StatefulWidget 
  @override
  _SignInState createState() => _SignInState();


class _SignInState extends State<SignIn> 
  TextEditingController phoneController = new TextEditingController();
  String phoneNumber = "";

  SharedPreferences logindata;
  bool newuser;

  bool shower = false;
  String smsCode;
  String verificationCode;

  @override
  void initState() 
    // TODO: implement initState
    super.initState();
    check_if_already_login();
  
  void check_if_already_login() async 
    logindata = await SharedPreferences.getInstance();
    newuser = (logindata.getBool('login') ?? true);
    print(newuser);
    if (newuser == false) 
      Navigator.pushReplacement(
          context, new MaterialPageRoute(builder: (context) => Home()));
    
  
  @override
  void dispose() 
    // Clean up the controller when the widget is disposed.
    phoneController.dispose();
    super.dispose();
  

  void _onCountryChange(CountryCode countryCode) 
    this.phoneNumber = countryCode.toString();
    print("New Country selected: " + countryCode.toString());
  

  void check() 
    final myPhone = this.phoneNumber + phoneController.text;
    print("Full Text: " + myPhone);
  
  Future<void> man() async

  
  Future<void> submit() async 
    final myPhone = this.phoneNumber + phoneController.text;
    final PhoneVerificationCompleted verificationCompleted =
        (AuthCredential credential) 

    ;


    final PhoneVerificationFailed verificationFailed =
        (AuthException exception) ;

    final PhoneCodeSent phoneCodeSent = (String verId, [int forceCodeResend]) 
      this.verificationCode = verId;
      smsCodeDialog(context).then((value) => print("signed"));
    ;

    final PhoneCodeAutoRetrievalTimeout autoRetrievalTimeout = (String verId) 
      this.verificationCode = verId;
    ;
    await FirebaseAuth.instance.verifyPhoneNumber(
        phoneNumber: myPhone,
        timeout: const Duration(seconds: 5),
        verificationCompleted: verificationCompleted,
        verificationFailed: verificationFailed,
        codeSent: phoneCodeSent,
        codeAutoRetrievalTimeout: autoRetrievalTimeout);
  

  Future<bool> smsCodeDialog(BuildContext context) 
    return showDialog(
        context: context,
        barrierDismissible: false,
        builder: (BuildContext context) 
          return AlertDialog(
            title: Text(
              'Enter Code',
              style: TextStyle(color: Colors.lightGreen, fontSize: 24),
            ),
            content: TextField(
              keyboardType: TextInputType.number,
              onChanged: (Value) 
                smsCode = Value;
              ,
            ),
            contentPadding: EdgeInsets.all(10),
            actions: [
              FlatButton(
                  onPressed: () 
                    String phone = phoneController.text;
                    if (phone != '') 
                      print('Successfull');
                      logindata.setBool('login', false);
                      logindata.setString('username', phone);
                      Navigator.push(context,
                          MaterialPageRoute(builder: (context) => Home()));
                    
                    else
                      Navigator.of(context).pop();
                      signIn();
                    
                    // FirebaseAuth.instance.currentUser().then((user) 
                    //   if (user != null) 
                    //     Navigator.of(context).pop();
                    //     Navigator.push(context,
                    //         MaterialPageRoute(builder: (context) => Home()));
                    //    else 
                    //     Navigator.of(context).pop();
                    //     signIn();
                    //   
                    // );
                  ,
                  child: Text(
                    'Verify',
                    style: TextStyle(fontSize: 20, color: Colors.lightGreen),
                  ))
            ],
          );
        );
    // CircularProgressIndicator(
    //   valueColor: new AlwaysStoppedAnimation<Color>(Colors.lightGreen),
    //   value: 0.25,
    // );

  

  signIn() 
    AuthCredential phoneAuthCredential = PhoneAuthProvider.getCredential(
        verificationId: verificationCode, smsCode: smsCode);
    FirebaseAuth.instance
        .signInWithCredential(phoneAuthCredential)
        .then((user) => Navigator.push(
            context, MaterialPageRoute(builder: (context) => Home())))
        .catchError((e) => print(e));
  

  @override
  Widget build(BuildContext context) 
    return GestureDetector(
      onTap: () 
        FocusScopeNode currentFocus = FocusScope.of(context);

        if (!currentFocus.hasPrimaryFocus) 
          currentFocus.unfocus();
        
      ,
      child: Scaffold(
        body: Column(
          //mainAxisAlignment: MainAxisAlignment.start,
          children: [
            Expanded(
              flex: 1,
              child: Container(
                height: MediaQuery.of(context).size.height,
                decoration: BoxDecoration(
                  gradient: LinearGradient(
                    begin: Alignment.topLeft,
                    end: Alignment.bottomRight,
                    stops: [0.1, 0.3, 1.0],
                    colors: [
                      Colors.lightGreen[300],
                      Colors.white,
                      Colors.lightGreen[50]
                    ],
                  ),
                ),
                child: Padding(
                  padding: const EdgeInsets.symmetric(vertical: 15),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      SizedBox(
                        height: 150,
                        child: Image.asset('images/phone.png'),
                      ),
                      SizedBox(
                        height: 20,
                      ),
                      Padding(
                        padding: const EdgeInsets.symmetric(horizontal: 20),
                        child: Container(
                          decoration: BoxDecoration(
                              borderRadius: BorderRadius.circular(50),
                              border: Border.all(color: Colors.lightGreen)),
                          width: double.infinity,
                          height: 40,
                          child: Padding(
                            padding: const EdgeInsets.symmetric(horizontal: 30),
                            child: Row(
                             // crossAxisAlignment: CrossAxisAlignment.start,
                              //mainAxisAlignment: MainAxisAlignment.spaceBetween,
                              children: [
                                CountryCodePicker(
                                  dialogTextStyle: TextStyle(fontSize: 20),
                                  onChanged: _onCountryChange,
                                  initialSelection: 'US',
                                  favorite: ['+251', 'ET'],
                                ),
                                Padding(
                                  padding: const EdgeInsets.only(bottom: 10),
                                  child: SizedBox(
                                    width: 150,
                                    child: TextFormField(
                                      controller: phoneController,
                                      keyboardType: TextInputType.phone,
                                      decoration: InputDecoration(
                                        border: InputBorder.none,
                                      ),
                                    ),
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ),
                      ),
                      SizedBox(
                        height: 20,
                      ),
                      MaterialButton(
                        onPressed: submit,
                        minWidth: MediaQuery.of(context).size.width - 80,
                        height: 45,
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(20)),
                        color: Colors.lightGreen,
                        splashColor: Colors.green,
                        child: Text(
                          "Confirm",
                          style: TextStyle(color: Colors.white, fontSize: 18),
                        ),
                      ),
                      Padding(
                        padding:
                            EdgeInsets.symmetric(vertical: 14, horizontal: 64),
                        child: Text(
                          "you'll receive a 6 digit code click Confirm to verify",
                          textAlign: TextAlign.center,
                          style: TextStyle(
                            fontSize: 22,
                            color: Colors.lightGreen,
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  

帮助我了解如何存储用户信息。

【问题讨论】:

【参考方案1】:

我从来没有使用过手机号登录,但我通常是这样的:

首先我让用户登录,然后我得到他们的 uid。它应该与您登录后获得的用户对象一起提供。

在 Firestore 中,我之前创建了一个集合“UserData”。

当我得到用户的 uid 时,我检查“UserData”中是否已经有一个文档。

如果没有,那么我继续创建文档并保存用户信息。

如果文档已经存在,我会阅读用户信息。

编辑:

以下是有关 SignIn 方法的所有文档:Here

用户登录后,您必须使用 Firestore,以便存储您以某种方式收集的用户信息。

这里是 Firestore 文档:Here

现在您需要了解用户是否是第一次登录。这取决于您。 当您获得此信息时:

如果是用户第一次登录,我会直接将信息添加到数据库中。这是一个示例(不要直接复制和粘贴此代码,因为正如我所说,流程很大程度上取决于您的应用代码)。


 CollectionReference users = FirebaseFirestore.instance.collection('users');

 users.add(
       'full_name': fullName, // John Doe
       'company': company, // Stokes and Sons
       'age': age // 42
     )
     .then((value) => print("User Added"))
     .catchError((error) => print("Failed to add user: $error"));
    

现在,每次“老”用户登录时,我都会使用 get 检索数据:

CollectionReference users = FirebaseFirestore.instance.collection('users');

users.doc(documentId).get()

【讨论】:

这可能是很多代码,并且很大程度上取决于您的应用程序。我将添加一些您可以使用的文档的详细信息和链接。

以上是关于在颤动中将登录的用户存储到云 Firestore的主要内容,如果未能解决你的问题,请参考以下文章

在用户/登录/登录屏幕中颤动令人困惑的行为

如何在颤动中将资产图像存储在缓存中

如何在颤动中将数据从复选框存储到 Firebase

在颤动中使用 REST api 将列表数据发送到云 Firestore 时出错

无法在颤动中将 blob 显示为图像

如何在颤动中将 Blob 转换为图像