在Flutter中,当使用手机OTP登录时,再次接收OTP,然后每次再次进入屏幕.我会做出改变



每当我保存我的项目或从亮模式切换到暗模式时,我都会收到OTP消息,表明代码已再次发送,或者转到重述屏幕,然后再次收到超时消息。为什么会这样?当我已经登录时?为什么用户已经在屏幕中了,却要重新查看屏幕?帮帮我。。下面是代码:-

这是我获得编号的第一个屏幕代码

child: Text("GET OTP", style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold)),
onPressed: () async {

if(_formKey.currentState.validate())  {
Map<String, dynamic> userinfo = {
'countryCode': phonecode,
'phone': _phoneController.text,
};
Navigator.pushNamed(context, '/OTPphoneLogin', arguments: userinfo);
}
},

这是第二个屏幕,用户必须在其中输入OTP:-

class _OTPphoneLogin extends State<OTPphoneLogin> {
final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
TextEditingController _pincontroller = TextEditingController();
final auth = FirebaseAuth.instance;
final CollectionReference _reference =     FirebaseFirestore.instance.collection("users");


String _countryCode = '';
String _phone = '';
String vid;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
final dynamic _args = ModalRoute.of(context).settings.arguments;
_maxScreenWidth = (MediaQuery.of(context).size.width <= 500) ?     MediaQuery.of(context).size.width : 500;
print(_args);
_phone = _args['phone'];
_countryCode = _args['countryCode'];

verifyNumber(_phone);
return WillPopScope(
//onWillPop: () async => false,
child: GestureDetector(
onTap:() => FocusScope.of(context).unfocus(),
child: Scaffold(
body: Center(
child: Container(
width: _maxScreenWidth, //how to set it to max
height: MediaQuery.of(context).size.height, //how to set it to max
child: SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(height: 50,),
Image.asset("assets/images/practicelogo.png"),
Padding(
padding: EdgeInsets.fromLTRB(25.0, 45.0, 25.0, 10.0),
child:   Text("OTP sent on:- " "n" +_countryCode.toString()+_phone.toString(),
style: TextStyle(fontSize: 25,color: mRed,
fontWeight: FontWeight.w500),textAlign: TextAlign.center,
),
),
SizedBox(height: 10),
Padding(
padding: EdgeInsets.fromLTRB(25.0, 15.0, 25.0, 10.0),
child: TextFormField(
keyboardType: TextInputType.number,
validator: _validateCode,
controller: _pincontroller ,
style: Theme.of(context).textTheme.subtitle1,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0)),
borderSide: BorderSide(color: lRed)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0)),
borderSide: BorderSide(color: mRed ,width: 3)),
hintText: "Enter OTP"),
),
),
SizedBox(
height: 80,
width: MediaQuery.of(context).size.width,
child: Padding(
padding: EdgeInsets.fromLTRB(25.0, 15.0, 25.0, 10.0),
child: ElevatedButton (
child: Text("Verify", style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold)),
onPressed:()=>verifyPhone(_pincontroller.text.trim()),
style: ElevatedButton.styleFrom(
primary: mRed,
onPrimary: mYellow,
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.7)
)
)
),
),
),

],
),
),
)
),
),
),
),
);
}
Future<void> verifyNumber(String mobile) async {
await FirebaseAuth.instance.verifyPhoneNumber(
phoneNumber: _countryCode+mobile,
timeout: const Duration(seconds: 60),
verificationCompleted: (PhoneAuthCredential credential) async {
try {

await FirebaseAuth.instance.signInWithCredential(credential);
Navigator.push(context, MaterialPageRoute(builder: (context)=>BottomNav()));
} on FirebaseAuthException catch(e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(e.message)));
}
},
verificationFailed: (FirebaseAuthException e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(e.message)));
},
codeSent: (String verificationId, int resendToken)  {
vid = verificationId;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Code Sent"+verificationId)));
},
codeAutoRetrievalTimeout: (String verificationId) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Timeout"+verificationId)));
},
);
}
Future<void> verifyPhone(String code) async {
PhoneAuthCredential phoneAuthCredential = PhoneAuthProvider.credential(verificationId: vid, smsCode: code);
try {
await FirebaseAuth.instance.signInWithCredential(phoneAuthCredential);
Navigator.push(context, MaterialPageRoute(builder: (context)=>BottomNav()));
} on FirebaseAuthException catch(e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(e.message)));
}
} 

并在控制台中获取此信息:-

E/zzf     (30955): **Problem retrieving SafetyNet**     Token: 7: 
W/System  (30955): Ignoring header X-Firebase-Locale   because its value was null.
W/System  (30955): **A resource failed to call end.** 
I/FirebaseAuth(30955): [FirebaseAuth:] Preparing to     create service connection to fallback implementation
W/System  (30955): Ignoring header X-Firebase-Locale    because its value was null.
W/FirebaseAuth(30955): **[SmsRetrieverHelper] Timed out waiting for SMS.**
W/System  (30955): Ignoring header X-Firebase-Locale      because its value was null.
D/FirebaseAuth(30955): Notifying id token listeners    about user ( ZuaQMaw8FxZb6jeiYKzXZJRplk52 ).
[FirebaseAuth:] Preparing to create service connection to fallback implementation

问题是在build命令中调用verifyNumber。每当状态_OTPphoneLogin更新时(每当它被重新渲染时,例如热重新加载时(,都会调用此函数。

您应该将其移动到initState,它只有在创建State时才会被调用,最佳做法是将其封装在登录检查中。您可以通过在调用verifyNumber之前检查FirebaseAuth.instance.currentUser?.uid是否为null来实现这一点。

最新更新