在Flutter中释放后使用TextEditingController

osh3o9ms  于 2023-05-19  发布在  Flutter
关注(0)|答案(2)|浏览(354)

我做了两个文本编辑控制器并初始化了它们。另外,我也在我的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(),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}
xpszyzbs

xpszyzbs1#

定义TextEditingController示例时,需要将它们标记为late final,然后在initState()函数中初始化它们,然后在dispose()中释放它们,如我在这里展示的:

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  late final TextEditingController _textController;

  @override
  void initState() {
    _textController = TextEditingController();
    super.initState();
  }

  @override
  void dispose() {
    _textController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    throw UnimplementedError();
  }

}
ztmd8pv5

ztmd8pv52#

我也遇到过类似的问题。这主要发生在类/小部件之间共享TextEditingController时。
例如,当您将外部TextEditingController传递到Widget中,但随后在Widget内部初始化TextEditingController时,它会检查是否传入了外部TextEditingController。如果为true,则将外部TextEditingController分配给内部TextEditingController,如果external为null,则使用新的TextEditingController进行初始化。

class MyStatefulWidgetState extends State<MyStatefulWidget> {
 
 ...

 late TextEditingController controller

 @override
 void initState() {
  super.initState();

  controller = widget.controller?? TextEditingController();
 }

 @override
 void dispose() {
  controller.dispose(); //this is wrong

  super.dispose();
 }

}

问题:大多数情况下,您不加选择地在TextEditingController上调用dispose(),有时会导致错误。
我注意到的是,您应该只在最初创建它们的类或小部件中部署TextEditingController,以避免此错误。所以你应该检查你是否有一个外部的TextEditingController,不要把它放在借用它的widget/class里面,而是把它放在它起源的地方。仅在创建TextEditingController的位置释放它。
注意:确保外部TextEditingController的父类/小部件在调用外部TextEditingController的小部件之前未被销毁。
因此处置上述控制器的正确方法是:

@override
 void dispose() {
  // go and dispose widget.controller in the class it originated from.
  if(widget.controller == null) { 
   controller.dispose();
  }

  super.dispose();
 }

相关问题