首页 > 解决方案 > 在 Flutter 中使用电话身份验证时无法更新 firebase 数据库中的数据

问题描述

我正在尝试将用户注册表单数据添加到 firebase 数据库。但是很难有效地做到这一点。我是新来的。我通过电话号码成功注册了用户,但无法添加相应的详细信息。我尝试使用 getter 和 setter,但它显然不起作用。我不知道这样做的理想方法是什么。我试着用谷歌搜索它,但没有得到任何帮助。我只是卡住了。我会很感激的。

这是我的代码

import 'package:firebase_auth/firebase_auth.dart';
import 'package:home_crisp/models/user.dart';
import 'package:home_crisp/services/auth.dart';
import 'package:provider/provider.dart';


class ChefRegisterScreen extends StatefulWidget {
  ChefRegisterScreen();

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

class _ChefRegisterScreenState extends State<ChefRegisterScreen> {
  final AuthService _auth = AuthService();

  bool loading = false;
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  String chefName = "", phoneNo = "";
  String smsCode, verificationID;
  String phnCode = "+92";
  DateTime dateOfBirth;
  bool codeSent = false;
  @override
  Widget build(BuildContext context) {
    final user = Provider.of<User>(context);
    final deviceSize = MediaQuery.of(context).size;
    return loading
        ? Loading()
        : Material(
            type: MaterialType.card,
            color: Color(0xffD4EBD3),
            child: Stack(
              children: <Widget>[

            // --> Here is the code of getting "chefname, phone and dateOfBirth" and setting them using setState() method 

                              //
                              // >>>>>>>>> Textfeild for getting OTP code 
                              //

                              codeSent
                                  ? // Here is the code for textfeild which get OTP code
                                  : Container(),

// ------------------------------------------------------   F I N I S H    B U T T O N

                              FlatButton(
                                onPressed: () async {



                                    if (user != null) {
                                      print(
                                          "TheRe IS  uSer already logging in so signing out logging in new user");
                                      AuthService().signOut();
                                    }

                                    if (codeSent) {
                                      AuthService().signInWithOTP(smsCode, verificationID);
                                    } else {
                                      verifyPhone(phoneNo);
                                    }

// ----> Here I tried to several methods to sent register form data to the seperate class named 
// ----> "user.dart" from where I tried to extract that info in "auth" signinWithPhoneNumber method.
// ----> I first tried to send the info via constructor

                                  ChefData(chefName: chefName,
                                          chefPhNo: phoneNo,
                                          chefDateOfBirth: dateOfBirth);
                                    }); 
// ----> Then I tried "setter" but in vain
                                    // ChefData().setChefName(chefName);
                                    // ChefData().setChefPhNo(phoneNo);
                                    // ChefData().setChefDateOfBirth(dateOfBirth);

                                child: ClipRRect(
                                  child: Text(
                                        "FINISH",
                                        style: TextStyle(
                                          color: Colors.white,
                                          fontFamily: 'Montserrat',
                                          fontSize: 20,
                                        ),
                                      ),
                                ),
                              ),



                            ],
                          ),
                        ),
                      )
                    ],
                  ),
                ),
              ],
            ),
          );
  }

  //
  // >>>>>>>>> S I G N   I N   W I T H   P H O M E  N U M B E R   P R O C E S S
  //
  Future<void> verifyPhone(phoneNo) async {
    final PhoneVerificationCompleted verificationComplete =
        (AuthCredential authResult) {
      print('1. Auto retrieving verification code');

      }
    };

    final PhoneCodeAutoRetrievalTimeout autoRetrieve = (String verID) {
      verificationID = verID;
      print("\n2. Auto retrieval time out");
    };

    final PhoneCodeSent smsCodeSent =
        (String verID, [int forceCodeResend]) async {
      verificationID = verID;
      setState(() {
        this.codeSent = true;
      });
      print("\n 3. Code Sent to " + phoneNo);
    };

    final PhoneVerificationFailed verificationFailed =
        (AuthException authException) {
      print('${AuthException(smsCode, "message")}');
      if (authException.message.contains('not authorized'))
        print('App not authroized');
      else if (authException.message.contains('Network'))
        print('Please check your internet connection and try again');
      else
        print('Something has gone wrong, please try later ' +
            authException.message);
    };

    await FirebaseAuth.instance
        .verifyPhoneNumber(
          phoneNumber: phoneNo,
          timeout: Duration(seconds: 50),
          verificationCompleted: verificationComplete,
          verificationFailed: verificationFailed,
          codeSent: smsCodeSent,
          codeAutoRetrievalTimeout: autoRetrieve,
        )
        .then((value) {})
        .catchError((error) {
      print(error.toString());
    });
  }
}

这是“auth.dart”类

import 'package:firebase_auth/firebase_auth.dart';
import 'package:home_crisp/models/user.dart';
import 'package:home_crisp/services/database.dart';

class AuthService {
  final FirebaseAuth _auth = FirebaseAuth.instance;

  // create user obj based on FirebaseUser

  User _userFormFirebaseUser(FirebaseUser user) {
    return user != null ? User(uid: user.uid) : null;
  }

  // auth change user stream
  Stream<User> get user {
    return _auth.onAuthStateChanged.map(_userFormFirebaseUser);
  }

  // ------------------------------------------------------ S I G N   I N   W I T H   P H O M E  N U M B E R

  signInWithPhoneNumber(AuthCredential authCreds) async {
    try {
      AuthResult result = await _auth.signInWithCredential(authCreds);
      FirebaseUser user = result.user;

      if (user != null) {
        print('AUTHENTICATONI SUCCESSFULL. Id: ' + user.uid);

// ---->> Now here I tried create a new document for the chef with the uid by extracting the chef data // // ---->> from "user.dart" class 

// ---->> I used getter method. I know there is going to be some better way to get that data

await DatabaseService(uid: user.uid).updateChefData(
            ChefData().getChefName(),
            ChefData().getChefPhNo(),
            ChefData().getChefDateOfBirth());

        return _userFormFirebaseUser(user);
      } else {
        print('Invalid code/invalid authentication');
      }
    } catch (e) {
      print(e.toString());
      return null;
    }
  }

  signInWithOTP(smsCode, verId) {
    AuthCredential authCreds = PhoneAuthProvider.getCredential(
        verificationId: verId, smsCode: smsCode);
    signInWithPhoneNumber(authCreds);
  }
}

这是包含“ChefData”类的“user.dart”文件,充当“auth.dart”和“chefRegisterScreen.dart”之间的中介

class User {

final String uid;
  User({this.uid});
}


class ChefData {
  String chefId;
  String chefName;
  String chefPhNo;
  DateTime chefDateOfBirth;

  ChefData({this.chefId, this.chefName, this.chefPhNo, this.chefDateOfBirth});

  // void setChefId(String _chefId) {
  //   this.chefId = _chefId;
  // }

  // void setChefName(String _chefName) {
  //   this.chefName = _chefName;
  // }

  // void setChefPhNo(String _chefPhNo) {
  //   this.chefPhNo = chefPhNo;
  // }

  // DateTime setChefDateOfBirth(DateTime _chefDateOfBirth) {
  //   this.chefDateOfBirth = _chefDateOfBirth;
  // }

  String getChefId() {
    return chefId;
  }

  String getChefName() {
    return chefName;
  }

  String getChefPhNo() {
    return chefPhNo;
  }

  DateTime getChefDateOfBirth() {
    return chefDateOfBirth;
  }
}

标签: firebaseflutterdartfirebase-authenticationregistration

解决方案


我遇到了类似的问题,我在注册期间使用共享首选项存储用户详细信息,然后在电话身份验证成功后上传详细信息。Shared preferences 是一个 Flutter 插件,可以让你以键值对的形式存储简单的数据。是有关共享首选项及其使用方法的更详细的文章。

在您的情况下,我建议您为共享偏好创建一个类。

class SharedPreference{
  static Future<String> storeChefData(ChefData chefData) async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  String storeUser = userToJson(chefData);
  await prefs.setString('user', storeUser);
  return storeUser;
 }

 static Future<ChefData> getChefData() async {
   SharedPreferences prefs = await SharedPreferences.getInstance();
   if (prefs.getString('user') != null) {
     ChefData chefData = userFromJson(prefs.getString('user'));
  return chefData;
  } else {
    return null;
   }
  }
 }

storeChefData()功能用于在注册期间存储用户详细信息。该getChefData()功能用于检索用户详细信息,以便在身份验证后上传到数据库。

在您的 user.dart 文件中,您将需要添加将 chefData 转换为 jsonData 以进行存储和从 jsonData 转换为 ChefData 以进行检索的函数,如上述函数所示。

ChefData userFromJson(String str) {
  final jsonData = json.decode(str);
  return ChefData.fromJson(jsonData);
}

String userToJson(ChefData data) {
  final dyn = data.toJson();
  return json.encode(dyn);
}

class ChefData{
  final String chefName;
  final String chefPhNo;
  final DateTime chefDateOfBirth;

  ChefData({this.chefName,this.chefPhNo,this.chefDateOfBirth});

  factory ChefData.fromJson(Map<String, dynamic> json) => ChefData(
    chefName: json["chefName"],
    chefPhNo: json["chefPhNo"]
    chefDateOfBirth: json["chefDateOfBirth"]
  );

  Map<String, dynamic> toJson() => {
     "chefName": chefName,
     "chefPhNo": chefPhNo
     "chefDateOfBirth": chefDateOfBirth
  };
}

在你的ChefRegistrationScreen你将添加:

await SharedPreference.storeChefData(ChefData(chefName: chefName,chefPhNo: phoneNo,chefDateOfBirth: dateOfBirth));

在您想要插入 chefData 的位置。

然后在您的auth.dart文件中添加:

ChefData getChefData = await SharedPreference.getChefData();
await DatabaseService(uid: user.uid).updateUserData(getChefData);

为了更新您的数据库。


推荐阅读