首页 > 解决方案 > 依赖下拉列表的第二个下拉列表仅在热重新加载后加载数据

问题描述

我正在构建一个依赖下拉列表,要求用户在第一个下拉列表中选择一个省,以便他们能够在第二个下拉列表中选择一个城市。我设法让代码按预期工作,但问题是,第二个下拉列表仅显示在热重新加载后从 API 获取的城市数据,尽管事实上在根据终端。如果我决定重新选择省,同样的事情也适用。我将每个 Dropdownlist 包装在 FutureBuilder 中,因为从 API 获取数据需要一些时间。

省API

Future<ProvinceModel> getProvince() async {
  var response = await http.get(Uri.parse(
    'https://rs-bed-covid-api.vercel.app/api/get-provinces'
  ));

  if(response.statusCode == 200) {
    print(response.body);
    return ProvinceModel.fromJson(json.decode(response.body));
  }
  else {
    throw Exception(
      'Something Went Wrong'
    );
  }
}

城市API

Future<CityModel> getCity(String id) async {
  var response = await http.get(Uri.parse(
    'https://rs-bed-covid-api.vercel.app/api/get-cities?provinceid=' + id
  ));
  print(id);

  if(response.statusCode == 200) {
    print(response.body);
    return CityModel.fromJson(json.decode(response.body));
  }
  else {
    throw Exception(
      'Something Went Wrong'
    );
   }
  }

省模式

class ProvinceModel {
      ProvinceModel({
        this.provinces,
      });

      List<Province> provinces;

      factory ProvinceModel.fromJson(Map<String, dynamic> json) => 
      ProvinceModel(
        provinces: List<Province>.from(json["provinces"].map((x) => 
        Province.fromJson(x))),
      );

      Map<String, dynamic> toJson() => {
        "provinces": List<dynamic>.from(provinces.map((x) => 
         x.toJson())),
      };
    }

class Province {
  Province({
     this.id,
     this.name,
  });

  String id;
  String name;

  factory Province.fromJson(Map<String, dynamic> json) => Province(
    id: json["id"],
    name: json["name"],
  );

  Map<String, dynamic> toJson() => {
    "id": id,
    "name": name,
  };
}

城市模型

class CityModel {
  CityModel({
    this.cities,
  });

  List<City> cities;

  factory CityModel.fromJson(Map<String, dynamic> json) => CityModel(
    cities: List<City>.from(json["cities"].map((x) => 
    City.fromJson(x))),
  );

  Map<String, dynamic> toJson() => {
    "cities": List<dynamic>.from(cities.map((x) => x.toJson())),
  };
}

class City {
 City({
    this.id,
    this.name,
  });

 String id;
 String name;

 factory City.fromJson(Map<String, dynamic> json) => City(
    id: json["id"],
    name: json["name"],
 );

 Map<String, dynamic> toJson() => {
    "id": id,
    "name": name,
 };
}

这是主要代码,

class HomeScreen extends StatefulWidget {


static Future province;
  static Future city;
  
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  ProvinceRepository provinceRepository = new ProvinceRepository();

  @override
  void initState() {
    super.initState();
    HomeScreen.province = provinceRepository.getProvince();
    HomeScreen.city = _CityDropDownState().getCity("id");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.red,
      body: Container(
        padding: const EdgeInsets.fromLTRB(16, 30, 16, 5),
        child: Center(
          child: Container(
            height: 250,
            width: 400,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(10),
              color: Colors.white
            ),
            child: Column(
              children: [
                FutureBuilder<ProvinceModel>(
                  future: HomeScreen.province,
                  builder: (context, snapshot) {
                    if (snapshot.data == null) {
                      return Container(
                        padding: const EdgeInsets.only(top: 70),
                        alignment: Alignment.center,
                        child: Column(
                          children: [
                            CircularProgressIndicator(
                              valueColor: AlwaysStoppedAnimation<Color>(Colors.red),
                            ),
                            SizedBox(height: 15),
                            Text(
                              'Mohon Tunggu Sebentar...',
                              style: TextStyle(
                                color: Colors.red,
                                fontSize: 15,
                                fontWeight: FontWeight.bold
                              ),
                            )
                          ],
                        ),
                      );
                    }
                    else {
                      return Container(
                        width: 300,
                        padding: const EdgeInsets.only(top: 50),
                        child: ProvinceDropDown(
                          province: snapshot.data,
                        ),
                      ); 
                    }
                  }
                ),
                SizedBox(height: 10),
                FutureBuilder<CityModel>(
                  future: HomeScreen.city,
                  builder: (context, snapshot) {
                    if (snapshot.connectionState == ConnectionState.waiting) {
                      return Container(
                        alignment: Alignment.center,
                        child: CircularProgressIndicator(
                          valueColor: AlwaysStoppedAnimation<Color>(Colors.red),
                        ),
                      );
                    }
                    else if (snapshot.data == null) {
                      return Container();
                    }
                    else if (snapshot.hasData){
                      return Container(
                        width: 300,
                        child: CityDropDown(
                          city: snapshot.data,
                        ),
                      );
                    }
                    else {
                      return null;
                    }
                  }
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

省份下拉

class ProvinceDropDown extends StatefulWidget {


final ProvinceModel province;
  static var selectedProvince;
  
  const ProvinceDropDown({ Key key, this.province }) : super(key: key);

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

class _ProvinceDropDownState extends State<ProvinceDropDown> {
  List<Province> provinceList;

  @override
  void initState() {
    provinceList = widget.province.provinces;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return DropdownButtonHideUnderline(
      child: ButtonTheme(
        alignedDropdown: true,
        child: DropdownButton<Province>(
          hint: Text(
            'PROVINSI'
          ),
          isExpanded: true,
          items: provinceList.map((item) {
            return DropdownMenuItem<Province>(
              child: Text(item.name),
              value: item,
            );
          }).toList(),
          onChanged: (Province value) {
            setState(() {
              CityDropDown.selectedCity = null;
              ProvinceDropDown.selectedProvince = value;
              HomeScreen.city = _CityDropDownState().getCity(ProvinceDropDown.selectedProvince.id); 
            });
          },
          value: ProvinceDropDown.selectedProvince,
        ),
      ),
    );
  }
}

城市下拉

class CityDropDown extends StatefulWidget {
  final CityModel city;
  static var selectedCity;

  const CityDropDown({ Key key, this.city }) : super(key: key);

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

class _CityDropDownState extends State<CityDropDown> {
  List<City> cityList;

  @override
  void initState() {
    super.initState();
    cityList = widget.city.cities;
  }
  
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        DropdownButtonHideUnderline(
          child: ButtonTheme(
            alignedDropdown: true,
            child: DropdownButton<City>(
              hint: Text(
                'KOTA/KABUPATEN'
              ),
              isExpanded: true,
              items: cityList.map((item) {
                return DropdownMenuItem<City>(
                  child: Text(item.name),
                  value: item,
                );
              }).toList(),
              onChanged: (City value) {
                setState(() {
                  CityDropDown.selectedCity = value;          
                });
              },
              value: CityDropDown.selectedCity,
            ),
          ),
        ),
        SizedBox(height: 10),
        InkWell(
          onTap: () {
            if(CityDropDown.selectedCity == null) {
              return showDialog(
                context: context, 
                builder: (context) {
                  return AlertDialog(
                    content: Text(
                      'Tolong pilih sebuah Kota atau Kabupaten',
                      textAlign: TextAlign.center,
                    ),
                  );
                }
              );
            }
            else {
              Navigator.push(
                context, 
                MaterialPageRoute(builder: (context) {
                  return HospitalScreen(
                    provinceID: ProvinceDropDown.selectedProvince.id,
                    cityID: CityDropDown.selectedCity.id,
                  );
                })
              );
            }
          },
          child: Container(
            margin: const EdgeInsets.only(top: 20),
            padding: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(10),
              color: Colors.red
            ),
            child: Text(
              'CARI',
              style: TextStyle(
                color: Colors.white,
                fontSize: 16
              ),
            ),
          ),
        )
      ],
    );
  }
}

抱歉,代码很长,我的问题是如何让 City Drop Down 显示获取的数据而无需热重新加载我的应用程序?提前致谢

标签: androidflutterdartrestflutter-futurebuilder

解决方案


推荐阅读