【问题标题】:variable gets reset when typing in flutter textfield在颤动文本字段中输入时变量被重置
【发布时间】:2021-06-05 23:01:11
【问题描述】:

我是 Flutter 移动应用程序的新手,并且创建了我的第一个应用程序。我正在了解它们是如何工作的。我今天发现,当我输入连接到控制器的文本字段时,整个页面似乎都被重新处理了。

当这种情况发生时,填充下拉按钮值的变量会被清空。变量名称是 _currentAgentState 并且当页面首次构建时一切正常,但是当我在任何文本字段小部件中键入第一个字母时,页面会重新构建并且变量为空。我已经在调试器的整个过程中跟踪了变量,但我看不到它在哪里被改变。任何见解将不胜感激。

final agentsRef = FirebaseFirestore.instance.collection(('agents'));
final agencyRef = FirebaseFirestore.instance.collection(('agency'));

class AgentProfileScreen extends StatefulWidget {
  static const String id = 'agent_profile_screen';
  final Agents agents;

  AgentProfileScreen([this.agents]);

  @override
  _AgentProfileScreenState createState() => _AgentProfileScreenState();
}

class _AgentProfileScreenState extends State<AgentProfileScreen> {
  final _db = FirebaseFirestore.instance;

  final emailController = TextEditingController();
  final passwordController = TextEditingController();
  final fNameController = TextEditingController();
  final lNameController = TextEditingController();
  final address1Controller = TextEditingController();
  final address2Controller = TextEditingController();
  final cityController = TextEditingController();
  final stateController = TextEditingController();
  final zipController = TextEditingController();
  final cellPhoneController = TextEditingController();
  final officePhoneController = TextEditingController();
  final agencyController = TextEditingController();

  @override
  void dispose() {
    emailController.dispose();
    passwordController.dispose();
    fNameController.dispose();
    lNameController.dispose();
    address1Controller.dispose();
    address2Controller.dispose();
    cityController.dispose();
    stateController.dispose();
    zipController.dispose();
    cellPhoneController.dispose();
    officePhoneController.dispose();
    agencyController.dispose();
    super.dispose();
  }

  bool showSpinner = false;
  String email;
  String password;
  String fName;
  String lName;
  String address1;
  String address2;
  String city;
  String state;
  String zip;
  String cellPhone;
  String officePhone;
  String agency;

  String _currentAgentState = globals.currentAgentState;
  String _currentAgencyState;
  String _currentAgency;

  getCurrentAgentProfile() async {
        //String currentAgencyId = currentAgentProfile.data()["agencyId"];

    if (globals.newAgent == true) {
      final DocumentSnapshot currentAgencyProfile =
          await agencyRef.doc(globals.agencyId).get();

      emailController.text = null;
      fNameController.text = null;
      lNameController.text = null;
      address1Controller.text = currentAgencyProfile.data()['address1'];
      address2Controller.text = currentAgencyProfile.data()['address2'];
      cityController.text = currentAgencyProfile.data()['city'];
      //stateController.text = currentAgencyProfile.data()['state'];
      //globals.currentAgencyState = currentAgencyProfile.data()['state'];
      //_currentAgentState = currentAgencyProfile.data()['state'];
      //_currentAgencyState = currentAgencyProfile.data()['state'];
      zipController.text = currentAgencyProfile.data()['zipCode'].toString();
      cellPhoneController.text = currentAgencyProfile.data()['cellPhone'];
      officePhoneController.text = currentAgencyProfile.data()['officePhone'];
      agencyController.text = currentAgencyProfile.data()['name'];
      // Updates State
      new Future.delayed(Duration.zero, () {
        final agentProvider =
        Provider.of<AgentProvider>(context, listen: false);
        agentProvider.loadValues(Agents());
      });
    } else {
      final DocumentSnapshot currentAgentProfile =
          await agentsRef.doc(globals.currentAgentId).get();

      // existing record
      // Updates Controllers
      emailController.text = currentAgentProfile.data()["email"];
      fNameController.text = currentAgentProfile.data()['fName'];
      lNameController.text = currentAgentProfile.data()['lName'];
      address1Controller.text = currentAgentProfile.data()['address1'];
      address2Controller.text = currentAgentProfile.data()['address2'];
      cityController.text = currentAgentProfile.data()['city'];
      //stateController.text = currentAgentProfile.data()['state'];
      _currentAgentState = currentAgentProfile.data()['state'];
      if (currentAgentProfile.data()['state'] == "" || currentAgentProfile.data()['state'] == null) {
        _currentAgencyState = globals.currentAgentState;
      } else {
        _currentAgencyState = currentAgentProfile.data()['state'];
      };
      zipController.text = currentAgentProfile.data()['zipCode'].toString();
      cellPhoneController.text = currentAgentProfile.data()['cellPhone'];
      officePhoneController.text = currentAgentProfile.data()['officePhone'];
      agencyController.text = currentAgentProfile.data()['agency'];
      //globals.currentAgentId = currentAgentProfile.data()['agentId'];
      // Updates State
      new Future.delayed(Duration.zero, () {
        final agentProvider =
        Provider.of<AgentProvider>(context, listen: false);
        agentProvider.loadValues(widget.agents);
      });
    }

  }

  List<DropdownMenuItem<String>> _dropDownState;

  List<DropdownMenuItem<String>> getDropDownState() {
    List<DropdownMenuItem<String>> items = [];
    for (String state in globals.states) {
      items.add(new DropdownMenuItem(
          value: state,
          child: new Text(
            state,
          )));
    }
    return items;
  }

  void changedDropDownState(String selectedState) {
    setState(() {
      _currentAgentState = selectedState;
      globals.selectedAgentState = selectedState;
      globals.currentAgentState = selectedState;
    });
  }

  void changedDropDownAgency(String selectedAgency) {
    setState(() {
      _currentAgency = selectedAgency;
      globals.selectedAgency = selectedAgency;
      globals.currentAgencyName = selectedAgency;
    });
  }

  @override
  void initState() {
    getCurrentAgentProfile();
    if (globals.currentAgentState == "" || globals.currentAgentState == null) {
      _currentAgentState = globals.currentAgencyState;
    } else{
      _currentAgentState = globals.currentAgentState;
    };
    _currentAgency = globals.agencyId;
    _currentAgencyState = globals.currentAgencyState;
    super.initState();

    _dropDownState = getDropDownState();
  }

  @override
  Widget build(BuildContext context) {
    // Get the stream of agents created in main.dart
    final agentProvider = Provider.of<AgentProvider>(context);
    final _firestoreService = FirestoreService();
    //String _chosenState = 'Select State';

    return Scaffold(
      appBar: AppBar(
        title: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Image.asset('assets/images/Appbar_logo.png',
                fit: BoxFit.cover, height: 56),
          ],
        ),
      ),
      backgroundColor: Colors.white,
      body: SafeArea(
        child: SingleChildScrollView(
          child: Padding(
            padding: const EdgeInsets.all(20.0),
            child: Column(
              children: <Widget>[
                Text(
                  'Agent Profile',
                  style: TextStyle(
                    fontSize: 30,
                  ),
                ),
                SizedBox(
                  height: 8.0,
                ),
                // Email entry text field
                TextField(
                  controller: fNameController,
                  keyboardType: TextInputType.text,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changefName(value);
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      hintText: 'First Name', labelText: 'First Name'),
                ),
                SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: lNameController,
                  keyboardType: TextInputType.text,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changelName(value);
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      hintText: 'Last Name', labelText: 'Last Name'),
                ),
                SizedBox(
                  height: 8.0,
                ),
                Container(
                  child: StreamBuilder(
                      stream: _db.collection('agency').snapshots(),
                      builder: (BuildContext context, AsyncSnapshot snapshot) {
                        if (snapshot.data == null) {
                          return Center(
                            child: CircularProgressIndicator(),
                          );
                        } else {
                          return new DropdownButton<String>(
                            hint: new Text("Select Agency"),
                            value: _currentAgency,
                            onChanged: changedDropDownAgency,
                            items: snapshot.data.docs
                                .map<DropdownMenuItem<String>>((document) {
                              return new DropdownMenuItem<String>(
                                value: document.id,
                                child: new Text(document.data()['name']),
                              );
                            }).toList(),
                          );
                        }
                      }),
                ),
                SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: address1Controller,
                  keyboardType: TextInputType.text,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changeaddress1(value);
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      hintText: 'Address 1', labelText: 'Address 1'),
                ),
                SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: address2Controller,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changeaddress2(value);
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      hintText: 'Address 2', labelText: 'Address 2'),
                ),
                SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: cityController,
                  keyboardType: TextInputType.emailAddress,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changecity(value);
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      hintText: 'City', labelText: 'City'),
                ),
                SizedBox(
                  height: 8.0,
                ),
                DropdownButton(
                  value: _currentAgentState,
                  items: _dropDownState,
                  hint: Text('Choose State'),
                  onChanged: changedDropDownState,
                ),
                SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: zipController,
                  keyboardType: TextInputType.number,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changezipCode(value);
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      hintText: 'Zip Code', labelText: 'Zip Code'),
                ),
                SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: cellPhoneController,
                  keyboardType: TextInputType.phone,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changecellPhone(value);
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      hintText: 'Cell Phone', labelText: 'Cell Phone'),
                ),
                SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: officePhoneController,
                  keyboardType: TextInputType.phone,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changeofficePhone(value);
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      hintText: 'Office Phone', labelText: 'Office Phone'),
                ),
                SizedBox(
                  height: 8.0,
                ),
                RoundedButton(
                  title: 'Save',
                  colour: Colors.blueAccent,
                  onPressed: () async {
                    setState(() {
                      showSpinner = true;
                    });
                    try {
                      agentProvider.saveAgent();
                      globals.currentAgentName = fNameController.value.text + ' ' + lNameController.value.text;
                      globals.currentAgentState = _currentAgentState;
                      await _firestoreService.saveDeviceToken();
                      Navigator.of(context).pushReplacement(MaterialPageRoute(
                          builder: (context) => AgentDashboardScreen()));

                      setState(() {
                        showSpinner = false;
                      });
                    } catch (e) {
                      // todo: add better error handling
                      print(e);
                    }
                  },
                ),
                SizedBox(
                  height: 8.0,
                ),

                (widget != null)
                    ? RoundedButton(
                        title: 'Delete',
                        colour: Colors.red,
                        onPressed: () async {
                          setState(() {
                            showSpinner = true;
                          });
                          try {
                            agentProvider.deleteAgent(globals.currentUid);
                            globals.targetScreen = 2;
                            Navigator.push(
                                context,
                                new MaterialPageRoute(
                                    builder: (context) => MainScreen()));
                            //Navigator.pushNamed(
                            //    context, AgentDashboardScreen.id);

                            setState(() {
                              showSpinner = false;
                            });
                          } catch (e) {
                            // todo: add better error handling
                            print(e);
                          }
                        },
                      )
                    : Container()
              ],
            ),
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          setState(() {
            showSpinner = true;
          });
          try {
            agentProvider.saveAgent();
            Navigator.push(
              context,
              new MaterialPageRoute(
                builder: (context) => AgentDashboardScreen(),
              ),
            );
            setState(() {
              showSpinner = false;
            });
          } catch (e) {
            // todo: add better error handling
            print(e);
          }
        },
        backgroundColor: kPrimaryColor,
        child: Icon(
          Icons.assignment_turned_in_outlined,
          color: Colors.blueAccent,
        ),
      ),
    );
  }
}

【问题讨论】:

    标签: flutter


    【解决方案1】:

    我今天发现,当我输入连接到控制器的文本字段时,整个页面似乎都被重新处理了。

    发生这种情况是因为您正在收听 AgentProvider 中的所有更改,并且您在输入任何内容时都在更改它

    onChanged: (值) { agentProvider.changefName(value); },

    如果您不希望每次AgentProvider 更改时都重建您的小部件。然后代替

    final agentProvider = Provider.of<AgentProvider>(context);
    

    这样做

    final agentProvider = Provider.of<AgentProvider>(context, listen: false);
    

    // 编辑

    How do I keep this variable from being reset to an empty string? 
    

    为此,在每次重建时将value 传递给controller,否则它将从空白字符串开始。

    可以这样实现:

     Widget build(BuildContext context) {
       // Get the stream of agents created in main.dart
       final agentProvider = Provider.of<AgentProvider>(context);
       final _firestoreService = FirestoreService();
       //String _chosenState = 'Select State';
    
       // pass the value for each controller
       fNameController.text(fName); // fname is the value you want as 
                       // the initial value now, you can get it from 
                       // your provider or anywhere.
    
       ...
       ...
    

    【讨论】:

    • 感谢您的解释。我接受页面重建,但第一次重建时变量 _currentAgentState 被设置为“”。我在使用该变量的每一行代码处都有断点,并且在重建期间停止的唯一断点位于“状态”的 DropdownButton 处。为什么会这样?如何防止此变量被重置为空字符串?
    • @LostTexan 我已经更新了答案,你可以试试
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    相关资源
    最近更新 更多