无法更改下拉按钮值 Flutter

Cannot change Dropdown button value Flutter

我想从firebase获取下拉按钮的初始值; 但是当我尝试在构建方法中设置 governorateDDValue = selectedUser.governorate; Dropdown 的值从 firebase 获取值,但我无法更改它

DropdownButton.gif

这是我的代码

class UserInfo extends StatefulWidget {
  static const routeName = '/UserInfoScreen';

  const UserInfo({Key? key}) : super(key: key);

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

class _UserInfoState extends State<UserInfo> {

  late User selectedUser;
  final date = DateFormat('yyyy-MM-dd').format(DateTime.now()).toString();

  var governorateDDValue;

  @override
  Widget build(BuildContext context) {

    final userList= Provider.of<List<User>>(context);
    final userID = ModalRoute.of(context)!.settings.arguments as String;
    selectedUser =
        userList.firstWhere((user) => user.id == userID);

    // this line makes dropdown value always equal to value from firestore
    governorateDDValue = selectedUser.governorate;

    return Scaffold(
      appBar: AppBar(
        title: Text('report'),
      ),
      body: SingleChildScrollView(
        child: Container(
          child: Row(
            children: <Widget>[
                    Text('Governorate',),
                    Container(height: 5),
                    DropdownButton<String>(
                      value: governorateDDValue,
                      icon: const Icon(Icons.arrow_downward),
                      iconSize: 24,
                      elevation: 16,
                      style: const TextStyle(color: Colors.deepPurple),
                      onChanged: (String? newValue) {
                        setState(() {
                          governorateDDValue = newValue!;
                        });
                      },
                      items: Constants.governoratesOfEgypt
                          .map<DropdownMenuItem<String>>((String value) {
                        return DropdownMenuItem<String>(
                          value: value,
                          child: Text(value),
                        );
                      }).toList(),
          ),
        ],
      ),
    ),
  ),
);

} }

提前致谢

你不能改变它的原因是每次调用setState你的build方法。因此,您的值将始终设置为 governorateDDValue = selectedUser.governorate; 因此,要允许更改,您应该将此 governorateDDValue = selectedUser.governorate; 放在 iniState

或者你可以这样做,这样它只会设置一次

class UserInfo extends StatefulWidget {
  static const routeName = '/UserInfoScreen';

  const UserInfo({Key? key}) : super(key: key);

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

class _UserInfoState extends State<UserInfo> {

  late User selectedUser;
  final date = DateFormat('yyyy-MM-dd').format(DateTime.now()).toString();
  bool initState = true; // ADD HERE
  var governorateDDValue;

  @override
  Widget build(BuildContext context) {

    final userList= Provider.of<List<User>>(context);
    final userID = ModalRoute.of(context)!.settings.arguments as String;
    selectedUser =
        userList.firstWhere((user) => user.id == userID);

    // this line makes dropdown value always equal to value from firestore
    if(initState){  // ADD HERE
    governorateDDValue = selectedUser.governorate; 
    initState = false;  // ADD HERE
    }

    return Scaffold(
      appBar: AppBar(
        title: Text('report'),
      ),
      body: SingleChildScrollView(
        child: Container(
          child: Row(
            children: <Widget>[
                    Text('Governorate',),
                    Container(height: 5),
                    DropdownButton<String>(
                      value: governorateDDValue,
                      icon: const Icon(Icons.arrow_downward),
                      iconSize: 24,
                      elevation: 16,
                      style: const TextStyle(color: Colors.deepPurple),
                      onChanged: (String? newValue) {
                        setState(() {
                          governorateDDValue = newValue!;
                        });
                      },
                      items: Constants.governoratesOfEgypt
                          .map<DropdownMenuItem<String>>((String value) {
                        return DropdownMenuItem<String>(
                          value: value,
                          child: Text(value),
                        );
                      }).toList(),
          ),
        ],
      ),
    ),
  ),
);
}

因为您在构建小部件中使用 governorateDDValue = selectedUser.governorate;,所以每次更改下拉菜单时都会重置其值 构建小部件将重建并且下拉列表的值将保持等于来自 firebase 的值 你应该在构建小部件之外使用 governorateDDValue = selectedUser.governorate; 这段代码应该可以工作

class UserInfo extends StatefulWidget {
  static const routeName = '/UserInfoScreen';

  const UserInfo({Key? key}) : super(key: key);

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

class _UserInfoState extends State<UserInfo> {

  var loading = false;

  late User selectedUser;
  final date = DateFormat('yyyy-MM-dd').format(DateTime.now()).toString();

  var governorateDDValue;


  @override
  void initState() {
    super.initState();
    loading = true;
    print('Future.delayed outside');
    print(loading);
    Future.delayed(Duration.zero, () {
      governorateDDValue = selectedUser.governorate;
      setState(() {
        loading = false;
      });
    });
  }


  @override
  Widget build(BuildContext context) {
    final userList = Provider.of<List<User>>(context);
    final userID = ModalRoute
        .of(context)!
        .settings
        .arguments as String;
    selectedUser =
        userList.firstWhere((user) => user.id == userID);

    // this line makes dropdown value always equal to value from firestore
    governorateDDValue = selectedUser.governorate;

    return Scaffold(
      appBar: AppBar(
        title: Text('report'),
      ),
      body: SingleChildScrollView(
        child: Container(
          child: Row(
            children: <Widget>[
              Text('Governorate',),
              Container(height: 5),
              DropdownButton<String>(
                value: governorateDDValue,
                icon: const Icon(Icons.arrow_downward),
                iconSize: 24,
                elevation: 16,
                style: const TextStyle(color: Colors.deepPurple),
                onChanged: (String? newValue) {
                  setState(() {
                    governorateDDValue = newValue!;
                  });
                },
                items: Constants.governoratesOfEgypt
                    .map<DropdownMenuItem<String>>((String value) {
                  return DropdownMenuItem<String>(
                    value: value,
                    child: Text(value),
                  );
                }).toList(),
              ),
            ],
          ),
        ),
      ),
    );