Someone can help me? I get errors when running the code.
This full code errors
Restarted application in 5,728ms.
D/EGL_emulation(12613): app_time_stats: avg=500967.44ms min=177.41ms max=1001757.50ms count=2
D/EGL_emulation(12613): app_time_stats: avg=1551.20ms min=1551.20ms max=1551.20ms count=1
E/flutter (12613): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: setState() called after dispose(): _LoginScreenState#96e43(lifecycle state: defunct, not mounted)
E/flutter (12613): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
E/flutter (12613): The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
E/flutter (12613): This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
E/flutter (12613): #0 State.setState.<anonymous closure>
E/flutter (12613): #1 State.setState
E/flutter (12613): #2 _LoginScreenState.build.<anonymous closure>
E/flutter (12613): #3 _LoginScreenState.build.<anonymous closure>
E/flutter (12613): #4 _rootRunUnary (dart:async/zone.dart:1434:47)
E/flutter (12613): #5 _CustomZone.runUnary (dart:async/zone.dart:1335:19)
E/flutter (12613): <asynchronous suspension>
E/flutter (12613):
This Login Page
import 'package:flutter/material.dart';
import 'package:login/api_service.dart';
import 'package:login/otp_verify.dart';
import 'package:login/login_page.dart';
import 'package:snippet_coder_utils/FormHelper.dart';
class LoginScreen extends StatefulWidget {
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
TextEditingController patientNoController = TextEditingController();
bool isAPICallProcess = false;
String patientPhoneNumber = ' 60176713856';
@override
Widget build(BuildContext context) {
final patientNoController = TextEditingController();
final logo = Hero(
tag: 'logo',
child: CircleAvatar(
backgroundColor: Colors.transparent,
radius: 40.0,
child: Image.network(
"https://i.imgur.com/bOCEVJg.png",
height: 180,
fit: BoxFit.contain,
),
),
);
final txtPatientNo = TextField(
controller: patientNoController,
decoration: InputDecoration(
hintText: 'Phone Number',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(30.0)
)
),
);
final btnLogin = RaisedButton(
child: Text("Verify"),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
onPressed: (){
if (patientNoController != null && patientNoController.text ==" 60176713856");
});
APIService.signin(patientPhoneNumber).then((respone) async {
setState(() {
isAPICallProcess = false;
});
if (respone) {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => OtpPage(
),
),
(route) => false,
);
}
},
);
return Scaffold(
appBar: AppBar(
title: Text("Patient Login Page"),
),
body: Center(
child: ListView(
shrinkWrap: true,
padding: EdgeInsets.only(left: 25, right: 25),
children: <Widget>[
logo,
SizedBox(height: 20,),
txtPatientNo,
SizedBox(height: 20,),
btnLogin,
],
),
),
);
}
}
Can anyone tell me where my mistake is? I'm new to using flutter. I want to use TextEditingControl and create an APICallProcess. But my problem. I stack the first page. Is my coding correct or not. Someone can explain to me so I can learn.
CodePudding user response:
This might happen because after you call setState
you immediately call Navigator.pushAndRemoveUntil
. setState
will execute the passed callback (in this case () {isAPICallProcess = false;}
, and marks to widget to be rebuilt.
But you Navigator
call can execute pretty quickly, so there is a chance when the engine tries to rebuild this login page of yours after setState
, it is no longer in the widget tree, and is disposed.
I don't know what do you use this isAPICallProcess
but my guess is that you do not really need it after this widget is disposed. So you can avoid this error message with this, checking for the widget's mounted state:
if (mounted) {
setState(() {
isAPICallProcess = false;
});
}
CodePudding user response:
My login page code - in MaterialPageRoute I have an error at patientPhoneNumber: patientPhoneNumber,
import 'package:flutter/material.dart';
import 'package:login/api_service.dart';
import 'otp_verify.dart';
class LoginScreen extends StatefulWidget {
const LoginScreen({Key? key}) : super(key: key);
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
bool isAPICallProcess = false;
String patientPhoneNumber = ' 60176713856';
final TextEditingController patientNoController = TextEditingController();
_LoginScreenState(){
patientNoController.text = ' 60176713856';
}
@override
Widget build(BuildContext context) {
final logo = Hero(
tag: 'logo',
child: CircleAvatar(
backgroundColor: Colors.transparent,
radius: 40.0,
child: Image.network(
"https://i.imgur.com/bOCEVJg.png",
height: 180,
fit: BoxFit.contain,
),
),
);
//TextField
final txtPatientNo = TextField(
controller: patientNoController,
decoration: InputDecoration(
hintText: 'Phone Number',
contentPadding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(30.0)
)
),
);
//Button
final btnLogin = RaisedButton(
child: const Text("Verify"),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
onPressed: (){
if (patientNoController != null && patientNoController.text ==" 60176713856");
});
//Signin
APIService.signin(patientPhoneNumber).then((respone) async {
if (mounted) {
setState(() {
isAPICallProcess = false;
});
if (respone) {
MaterialPageRoute(
builder: (context) => OtpPage(
patientPhoneNumber: patientPhoneNumber,
)
);
(route) => false;
}
}
},
);
return Scaffold(
appBar: AppBar(
title: const Text("Patient Login Page"),
),
body: Center(
child: ListView(
shrinkWrap: true,
padding: const EdgeInsets.only(left: 25, right: 25),
children: <Widget>[
logo,
const SizedBox(height: 20,),
txtPatientNo,
const SizedBox(height: 20,),
btnLogin,
],
),
),
);
}
@override
void dispose() {
patientNoController.dispose();
super.dispose();
}
}
My otp verify page code
import 'package:flutter/material.dart';
import 'api_service.dart';
import 'appoinment_list.dart';
class OtpPage extends StatefulWidget {
_otpPageVerifyState createState() => _otpPageVerifyState();
}
class _otpPageVerifyState extends State<OtpPage> {
bool isAPICallProcess = false;
String otpVerifyNo = '134679';
final TextEditingController otpVerifyNoController = TextEditingController();
_otpPageVerifyState(){
otpVerifyNoController.text = '134679';
}
@override
Widget build(BuildContext context) {
final logo = Hero(
tag: 'logo',
child: CircleAvatar(
backgroundColor: Colors.transparent,
radius: 40.0,
child: Image.network(
"https://i.imgur.com/6aiRpKT.png",
height: 180,
fit: BoxFit.contain,
),
),
);
//TextField
final txtotpVerify = TextField(
controller: otpVerifyNoController,
decoration: InputDecoration(
hintText: 'OTP Number',
contentPadding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(30.0)
)
),
);
//Button
final btnLogin = RaisedButton(
child: const Text("Verify"),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
onPressed: (){
if (otpVerifyNoController != null && otpVerifyNoController.text =="134679");
});
//Signin
APIService.verifyOTP(otpVerifyNo).then((respone) async {
if (mounted) {
setState(() {
isAPICallProcess = false;
});
if (respone!.isNotEmpty){
MaterialPageRoute(
builder: (context) => AppoinmentList(
token: respone,
)
);
}
}
},
);
return Scaffold(
appBar: AppBar(
title: const Text("Patient Login Page"),
),
body: Center(
child: ListView(
shrinkWrap: true,
padding: const EdgeInsets.only(left: 25, right: 25),
children: <Widget>[
logo,
const SizedBox(height: 20,),
txtotpVerify,
const SizedBox(height: 20,),
btnLogin,
],
),
),
);
}
@override
void dispose() {
otpVerifyNoController.dispose();
super.dispose();
}
}
My API service page
import 'dart:async';
import 'dart:convert' show json;
import 'package:http/http.dart' as http;
class APIService {
/*
use the phone number and otp below
phone: 60176713856
otp: 134679
Step:
1. Signin
2. Verify OTP
3. Get an appointment list
*/
static Future<String?> verifyOTP(otp) async {
var url =
'https://us-central1-cheart.cloudfunctions.net/api_v2/consumerWebVerifyOTP';
Map data = {
"API": "ConsumerWebVerifyOTP",
"Token": "",
"Data": {
"tokenType": "jwt",
"otpNumber": otp.trim(),
}
};
//encode Map to JSON
var body = json.encode(data);
var response = await http.post(Uri.parse(url),
headers: {"Content-Type": "application/json"}, body: body);
if (response.statusCode == 200) {
var result = json.decode(response.body.toString());
if (result['ResponseCode'] == "0") {
var token = result['Data']['token'];
return token;
} else if (result['ResponseCode'] != "0") {
return null;
}
}
}
static Future<bool> signin(patientPhoneNumber) async {
bool ret = false;
var url =
"https://us-central1-cheart.cloudfunctions.net/api_v2/consumerWebLogin";
Map data = {
"API": "ConsumerWebLogin",
"Token": "",
"Data": {
"tokenType": "jwt",
"patientPhoneNumber": patientPhoneNumber.trim(),
}
};
try {
//encode Map to JSON
var body = json.encode(data);
var response = await http.post(Uri.parse(url),
headers: {"Content-Type": "application/json"}, body: body);
if (response.statusCode == 200) {
var result = json.decode(response.body.toString());
if (result['ResponseCode'] == "0") {
ret = true;
} else if (result['ResponseCode'] != "0") {
ret = false;
}
}
} catch (e) {
ret = false;
}
return ret;
}
static Future<String?> getAppointmentList(String token) async {
var url =
'https://us-central1-cheart.cloudfunctions.net/api_v2/consumerWebGetPatientAppointment';
Map data = {
"API": "UserGetWebCallAppointmentList",
"Token": token,
"Data": {"tokenType": "jwt", "appointmentStatus": 0}
};
//encode Map to JSON
var body = json.encode(data);
var response = await http.post(Uri.parse(url),
headers: {"Content-Type": "application/json"}, body: body);
if (response.statusCode == 200) {
var result = json.decode(response.body.toString());
if (result['ResponseCode'] == "0") {
// if (result['Data'] != null) {
// // convert into list
// }
return result['ResponseMsg'];
} else if (result['ResponseCode'] != "0") {
if (result['ResponseCode'] == "1") {}
}
}
}
}
The appointment list page is still not complete
import 'package:flutter/material.dart';
import 'api_service.dart';
class AppoinmentList extends StatefulWidget {
final String token;
const AppoinmentList({
Key? key,
required this.token,
}) :super(key: key);
@override
_AppoinmentListState createState() => _AppoinmentListState();
}
class _AppoinmentListState extends State<AppoinmentList> {
@override
void initState() {
super.initState();
APIService.getAppointmentList(widget.token);
}
@override
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
}
When I enter the phone number on the login page and click the button verify. I can't go to the OTP page. I don't know why. Can check my code if my code has wrong. I hope you can help me.
Phone number: 60176713856
OTP number: 134679