一个 TextEditingController 被销毁后使用调用了一个可重用的输入字段类,我在其中传递了这个控制器

问题描述

我创建了一个可重复使用的字段,该字段被调用以在我的应用程序的不同屏幕中的表单中显示不同的字段,我还传递了一个控制器,但是当处置控制器时,它会显示错误,如果我返回到同一个表单屏幕它崩溃了。

class EntryField extends StatefulWidget {
  @override
  _EntryFieldState createState() => _EntryFieldState();
  final String title;
  final TextEditingController controller;
  final TextInputType inputType;
  final FilteringTextInputFormatter filter;
  final hintText;
  EntryField({@required this.title,this.hintText,@required this.controller,@required this.inputType,@required this.filter});
}
class _EntryFieldState extends State<EntryField> {
  @override
  void dispose() {
    widget.controller.dispose();
    print("anything");
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.symmetric(vertical: 10),child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[
          Text(
              this.widget.title,style: GoogleFonts.quicksand(
                fontSize: 18,)
          ),SizedBox(
            height: 10,),TextFormField(
            controller: this.widget.controller,keyboardType: this.widget.inputType,inputFormatters: <TextInputFormatter>[
              this.widget.filter,],validator: (value){
              if(value.isEmpty){
                return "${this.widget.title} is a required Field";
              }
              return null;
            },decoration: Inputdecoration(
              hintText: this.widget.hintText,border: InputBorder.none,fillColor: Color(0xfff3f3f4),filled: true,errorBorder: new OutlineInputBorder(
                borderSide: new BorderSide(color: Colors.red),errorStyle: TextStyle(
                fontSize: 15,);
  }
}

在这个类中,我传递了它的字段值

final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final _serviceTitleController = TextEditingController();
final _serviceCategoryController = TextEditingController();
final _servicePriceController = TextEditingController();
ToastErrorMessage _error = ToastErrorMessage();
ToastValidMessage _valid = ToastValidMessage();

class AddServices extends StatefulWidget {
  @override
  _AddServicesstate createState() => _AddServicesstate();
}

class _AddServicesstate extends State<AddServices> {

  int currentIndex;
  String _cityName;
  final WorkshopServiceQueries _add = WorkshopServiceQueries();
  final _firebaseUser = FirebaseAuth.instance.currentUser;

  @override
  void initState() {
    cityName();
    super.initState();
    currentIndex = 0;
  }
  @override
  void dispose() {
    print("hello");
    super.dispose();
  }
  void clearControllerText(){
    _serviceTitleController.clear();
    _serviceCategoryController.clear();
    _servicePriceController.clear();

  }

  Future cityName() async{
   _cityName = await _add.getWorkshopCityName();
  }

  changePage(int index) {
    setState(() {
      currentIndex = index;
    });
  }
  validateFields() async{

    final ValidateWorkshopServices service = ValidateWorkshopServices();
    final int _price = int.tryParse(_servicePriceController.text.trim());
    if(!service.validateServiceCategory(_serviceCategoryController.text.trim()) && !service.validateServiceTitle(_serviceTitleController.text.trim()) && !service.validateServicePrice(_price)){
      _error.errorToastMessage(errorMessage: "Enter Valid Data in Each Field");
    }
    else if(!service.validateServiceCategory(_serviceCategoryController.text.trim())){
      _error.errorToastMessage(errorMessage: "Service Category Must Only contain Alphabets");
    }
    else if(!service.validateServiceTitle(_serviceTitleController.text.trim())){
      _error.errorToastMessage(errorMessage: "Service Title Must Only contain Alphabets");
    }
    else if(!service.validateServicePrice(_price)){
      _error.errorToastMessage(errorMessage: "Service Price must be less than or equal to 2000");
    }
    else{
     await addService(_price);
    }
  }
  Future<void> addService(int price) async{
  try {

      Services data = Services(title: _serviceTitleController.text.trim(),category: _serviceCategoryController.text.trim(),price: price,workshopCity: _cityName,workshopId: _firebaseUser.uid);
      await _add.addWorkshopService(data);
      if(WorkshopServiceQueries.resultMessage == WorkshopServiceQueries.completionMessage){
        _valid.validToastMessage(validMessage: WorkshopServiceQueries.resultMessage);
        clearControllerText();
        Future.delayed(
          new Duration(seconds: 2),(){
            Navigator.pop(context);
          },);
      }
      else{
        _error.errorToastMessage(errorMessage: WorkshopServiceQueries.resultMessage);
      }
    }catch(e){
       _error.errorToastMessage(errorMessage: e.toString());
    }
}

  @override
  Widget build(BuildContext context) {

    final height = MediaQuery.of(context).size.height;
    int _checkBoxValue;
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text(
            'BIKERSWORLD',style: GoogleFonts.quicksand(
              color: Colors.white,fontSize: 18,backgroundColor: Color(0XFF012A4A),leading: IconButton(icon:Icon(Icons.arrow_back,color: Colors.orange,onpressed:() => Navigator.pop(context),)
        ),body: Container(
          height: height,child: Stack(
            children: <Widget>[
              Container(
                padding: EdgeInsets.symmetric(horizontal: 20),child: SingleChildScrollView(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[
                      SizedBox(height: 30,_title(),SizedBox(height: 40),_addServicesWidget(),SizedBox(height: 20),FlatButton(
                      child: Container(
                        padding: EdgeInsets.symmetric(vertical: 15),alignment: Alignment.center,decoration: Boxdecoration(
                            borderRadius: BorderRadius.all(Radius.circular(5)),BoxShadow: <BoxShadow>[
                              BoxShadow(
                                  color: Colors.grey.shade200,offset: Offset(2,4),blurRadius: 5,spreadRadius: 2)
                            ],gradient: LinearGradient(
                                begin: Alignment.centerLeft,end: Alignment.centerRight,colors: [Color(0xfffbb448),Color(0xfff7892b)])),child: Text(
                          'Register Now',style: GoogleFonts.krub(
                            fontSize: 18,color: Colors.white,onpressed: (){
                        if(!_formKey.currentState.validate()){
                          return;
                        }
                        else{
                          validateFields();
                        }
                      },);
  }
}
Widget _addServicesWidget() {
  return Form(
    key: _formKey,autovalidateMode: AutovalidateMode.disabled,child: Column(
      children: <Widget>[
        EntryField(title: "Category",hintText: 'Mechanical',controller: _serviceCategoryController,inputType: TextInputType.text,filter: FilteringTextInputFormatter.allow(RegExp("[a-zA-Z ]"))),SizedBox(height:15,EntryField(title: "Title",hintText: 'wheel barring',controller: _serviceTitleController,EntryField(title: "Price",hintText: 'price < 2000',controller: _servicePriceController,inputType: TextInputType.number,filter:FilteringTextInputFormatter.digitsOnly),);
}

解决方法

您不应从小部件内部处置控制器,因为您是在小部件外部创建它并将对它的引用传递给小部件。

看起来您的控制器是在全局范围内创建的 - 如果是这样,并且如果它们打算在应用的整个生命周期中使用,则不应处置它们。

所以要么

  • 不要处置控制器,如果它们是全局变量
  • 或者从同一个“所有者”对象创建和处理它们