我做了两个文本编辑控制器并初始化了它们。另外,我也在我的initState中初始化了它们,这样当我的屏幕被释放时,它们可以再次初始化,那么为什么我会得到这个错误呢?这两个文本控制器用于不同的地方,OTPBackButton是将我们带回到上一个屏幕的小部件。
当我第一次打开此屏幕时,它工作正常,但当我单击此OTPBackButton(或仅返回按钮)并再次返回此屏幕时,此错误显示给我。
我包括完整的部件,如果它帮助-
class MobileInput extends StatefulWidget {
final bool isOTP;
final bool isSignup;
VoidCallback signUpState;
TwoArgumentEventCallback signInWithOTP;
Callback sendOTP;
MobileInput({
this.isOTP = true,
required this.sendOTP,
required this.signInWithOTP,
required this.signUpState,
this.isSignup = false,
});
@override
_MobileInputState createState() => _MobileInputState();
}
class _MobileInputState extends State<MobileInput> {
.....
TextEditingController contactController = TextEditingController();
TextEditingController otpController = TextEditingController();
.....
@override
void initState() {
...
contactController = TextEditingController();
otpController = TextEditingController();
super.initState();
}
@override
void dispose() {
// contactController.dispose();
// otpController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
.........
(isOTP)
? Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: text.bodyText2!
.apply(color: secondaryTextColor),
children: [
TextSpan(
text:
'We sent a verification code to your\nphone number '),
TextSpan(
text: (contactController.text.isNotEmpty)
? '(+91) ' +
contactController.text.toString()
: '',
style:
text.bodyText2!.apply(color: brandPurple),
),
],
),
),
)
: Container(),
SizedBox(
height: getProportionateScreenWidth(32),
),
isOTP
? PinCodeTextField(
animationType: AnimationType.scale,
focusNode: focusNode,
onChanged: (value) {
print(otpController.text + ' after input');
if (otpController.text.length < 6) {
setState(() {
isDisabled = true;
});
}
},
.....
),
onCompleted: (value) {
otpController.text = value;
setState(() {
otpButtonText = "Verify Phone Number";
isDisabled = false;
});
},
)
: CustomTextField(
.....
onChanged: (value) {
if (isSignup) {
if (contactController.text.length == 10) {
FocusScope.of(context).unfocus();
emailEntered = true;
if (checkboxValue) {
setState(() {
isDisabled = false;
});
} else {
setState(() {
isDisabled = true;
});
}
} else {
setState(() {
isDisabled = true;
});
}
} else {
if (contactController.text.length == 10) {
FocusScope.of(context).unfocus();
emailEntered = true;
setState(() {
isDisabled = false;
});
} else {
setState(() {
isDisabled = true;
});
}
}
},
......
),
.....
......
isOTP
? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Didn\'t received?',
style: text.bodyText2!.apply(color: Colors.white),
),
TextButton(
onPressed: () {
setState(() {
otpController.clear();
focusNode.requestFocus();
// autoFocus = true;
});
(otpController.text.isEmpty)
? widget.sendOTP(contactController.text)
: null;
},
child: RichText(
........
)
: Container(),
SizedBox(height: getProportionateScreenWidth(20)),
isOTP
? LoginCTA(
//After input otp
onPressed: () async {
.....
if (emailEntered &&
otpController.text.length == 6) {
bool res;
try {
res = await widget.signInWithOTP(
contactController.text, otpController.text);
} catch (e) {
res = false;
print(e);
}
..............
LoginCTA(
//After input mobile number
onPressed: () async {
if (emailEntered &&
contactController.text.length == 10) {
widget.sendOTP(contactController.text);
setState(() {
isOTP = true;
isDisabled = true;
});
} else {
......
}
},
.......
),
SizedBox(height: getProportionateScreenWidth(28)),
!isOTP
? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
(isSignup)
? 'Already have an account? '
: 'Don\'t have an account? ',
style: TextStyle(
fontSize: 16,
color: Colors.white,
),
),
GestureDetector(
onTap: () => setState(() {
isSignup = !isSignup;
if (isSignup) {
if (contactController.text.length == 10) {
FocusScope.of(context).unfocus();
emailEntered = true;
if (checkboxValue) {
setState(() {
isDisabled = false;
});
} else {
setState(() {
isDisabled = true;
});
}
} else {
setState(() {
isDisabled = true;
});
}
} else {
if (contactController.text.length == 10) {
FocusScope.of(context).unfocus();
emailEntered = true;
setState(() {
isDisabled = false;
});
} else {
setState(() {
isDisabled = true;
});
}
}
}),
.......
],
)
: Container(),
],
),
),
],
),
),
);
}
}
2条答案
按热度按时间xpszyzbs1#
定义
TextEditingController
示例时,需要将它们标记为late final
,然后在initState()
函数中初始化它们,然后在dispose()
中释放它们,如我在这里展示的:ztmd8pv52#
我也遇到过类似的问题。这主要发生在类/小部件之间共享TextEditingController时。
例如,当您将外部TextEditingController传递到Widget中,但随后在Widget内部初始化TextEditingController时,它会检查是否传入了外部TextEditingController。如果为true,则将外部TextEditingController分配给内部TextEditingController,如果external为null,则使用新的TextEditingController进行初始化。
问题:大多数情况下,您不加选择地在TextEditingController上调用dispose(),有时会导致错误。
我注意到的是,您应该只在最初创建它们的类或小部件中部署TextEditingController,以避免此错误。所以你应该检查你是否有一个外部的TextEditingController,不要把它放在借用它的widget/class里面,而是把它放在它起源的地方。仅在创建TextEditingController的位置释放它。
注意:确保外部TextEditingController的父类/小部件在调用外部TextEditingController的小部件之前未被销毁。
因此处置上述控制器的正确方法是: