微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么我的应用程序使用 ChangeNotifierProvider 开发更新一级延迟?

如何解决为什么我的应用程序使用 ChangeNotifierProvider 开发更新一级延迟?

我正在开发一个 Flutter 应用程序,我使用 ChangeNotifierProvider 来管理状态。我有一个名为“Data”的类,它是应用程序的模型(MVC 设计模式中的模型)和一个名为“DataManager”的类,它是应用程序的模型是应用程序的控制器(MVC 设计模式中的控制器)并在其中创建一个 Data 实例。 我在我的 main 中创建了 ChangeNotifierProvider 的实例,ChangeNotifier 是 DataManager。所以DataManager 中的方法调用notifyListeners() 方法。 当我运行应用程序时,我添加一个磁贴,尽管添加了磁贴,但它的 UI 不会改变。添加一个磁贴后,第一个磁贴出现,依此类推。应用程序始终落后于用户一个级别。 你能帮我解决这个问题吗?

这是 main.dart:

main(){
  runApp(MyApp());
}

class MyApp extends StatefulWidget{
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => DataManager(),child: MaterialApp(
          home: LoadingScreen()
      ),);
  }
}

这是 Data.dart(这里的方法可能并不重要):

class Data{
  Position _location;
  List<CityTile> _cityWidgets = List<CityTile>();
  List<Weather> _weatherDatas = List<Weather>();

  Future<Position> getLocation() async {
    bool serviceEnabled;
    LocationPermission permission;

    serviceEnabled = await Geolocator.isLocationServiceEnabled();
    if (!serviceEnabled) {
      print('Location services are disabled.');
      return Future.error('Location services are disabled.');
    }

    permission = await Geolocator.checkPermission();
    if (permission == LocationPermission.deniedForever) {
      print('Location permissions are permanently denied,we cannot request permissions.');
      return Future.error(
          'Location permissions are permanently denied,we cannot request permissions.');
    }

    if (permission == LocationPermission.denied) {
      permission = await Geolocator.requestPermission();
      if (permission != LocationPermission.whileInUse &&
          permission != LocationPermission.always) {
        print( 'Location permissions are denied (actual value: $permission).');
        return Future.error(
            'Location permissions are denied (actual value: $permission).');
      }
    }

    _location = await Geolocator.getCurrentPosition();
    return _location;
  }

  void addCity({Weather cityWeather}) async{
    bool isReady = await cityWeather.updateWeather();
    String cityName = cityWeather.getCity;
    if(!cityExists(cityName) && isReady) {
      _weatherDatas.add(cityWeather);
      _cityWidgets.add(CityTile(cityName));
    }
    // print("widgets:");
    // for(CityTile cityTile in _cityWidgets){
    //   print("${cityTile.city} widget exists");
    // }
    // print("weathers:");
    // for(Weather weather in _weatherDatas){
    //   print("${weather.getCity} weather exists");
    // }
  }

  Weather searchWeather({String cityName}){
    for(Weather weather in _weatherDatas){
      if(weather.getCity == cityName){
        return weather;
      }
    }
    return null;
  }

  bool cityExists(String cityName){
    if(searchWeather(cityName: cityName) == null)
      return false;
    else
      return true;
  }

  void removeCity({String cityName}) {
    if (cityExists(cityName)) {
      _removeCityWidget(cityName: cityName);
      _removeCityWeather(cityName: cityName);
    }
  }

  void _removeCityWidget({String cityName}){
    CityTile cityTiletoRemove;
    for(CityTile cityTile in _cityWidgets){
      if(cityTile.city == cityName){
        cityTiletoRemove = cityTile;
      }
    }
    if(cityTiletoRemove != null)
      _cityWidgets.remove(cityTiletoRemove);
  }

  void _removeCityWeather({String cityName}){
    Weather weather = searchWeather(cityName: cityName);
    if(weather != null)
      _weatherDatas.remove(weather);
  }

  int widgetNumbers(){
    return _cityWidgets.length;
  }

  get weatherDatas{
    return List.unmodifiable(_weatherDatas);
  }

  get cityWidgets{
    return List.unmodifiable(_cityWidgets);
  }
}

这是 DataManager.dart:

class DataManager extends ChangeNotifier{
  Data data = Data();

  Future<bool> findWeatherByLocation() async{
    Position location = await data.getLocation();
    // print("long : ${location.longitude} and lat : ${location.latitude}");
    Weather weatherOfhere = Weather(city: null);
    String weatherCast = "";

    if(location == null){
      // print("location is null");
      return false;
    }

    for(int i=0; i<5; i++){
      weatherCast = await weatherOfhere.getCurrentWeather(location: location);
      if(weatherCast.isNotEmpty)
        break;
    }
    if( weatherCast.isEmpty || jsonDecode(weatherCast)['cod'] == '404') {
      // print("city not found");
      return false;
    }
    // print("weathercast : $weatherCast");

    addCityByWeather(weatherOfhere);
    return true;
  }

  void addCityByWeather(Weather cityWeather){
    data.addCity(cityWeather: cityWeather);
    notifyListeners();
  }

  void addCityByName(String city) async{
    if(!data.cityExists(city) && city.isNotEmpty){
      Weather cityWeather = Weather(city: city);
      bool isRealCity = await cityWeather.updateWeather();
      if(isRealCity) {
        data.addCity(cityWeather: cityWeather);
      }
    }
    notifyListeners();
  }

  void removeCity(String city){
    data.removeCity(cityName: city);
    notifyListeners();
  }

  int cityNumbers(){
    return data.widgetNumbers();
  }

  Future<bool> updateWeather(String city) async{
    Weather weatherToUpdate = data.searchWeather(cityName: city);
    bool isUpdated = false;
    if(weatherToUpdate == null){
      return false;
    }
    else{
      isUpdated = await weatherToUpdate.updateWeather();
      notifyListeners();
    }
    return isUpdated;
  }

  get weatherDatas{
    return data.weatherDatas;
  }

  get cityWidgets{
    return data.cityWidgets;
  }

  void addOption(String option){
    option = option.toLowerCase() == 'feels like' ? 'feels_like' : option;
    options[option.toLowerCase()] = true;
    //updateall();
    notifyListeners();
  }

  void removeOption(String option){
    option = option.toLowerCase() == 'feels like' ? 'feels_like' : option;
    options[option.toLowerCase()] = false;
    // updateall();
    notifyListeners();
  }

  void updateall(){
    for(Weather weather in data.weatherDatas)
      weather.updateWeather();
    notifyListeners();
  }

  bool isOptionSelected(String option){
    option = option.toLowerCase() == 'feels like' ? 'feels_like' : option;
    // print("in isOptionSelected: ${options[option.toLowerCase()]}");
    return options[option.toLowerCase()];
  }

  Color getoptionButtonColor(String option){
    option = option.toLowerCase() == 'feels like' ? 'feels_like' : option;
    return isOptionSelected(option) ? Colors.indigo : Colors.black38;
  }

  get getoptions{
    return options;
  }

  String getWeatherScreenPicture(String city){
    Weather weatherData = data.searchWeather(cityName: city);
    int id = weatherData.id;

    if(id == 800){
      var Now = new DateTime.Now();
      List clearSky = codetoPicture[800];
      if( Now.hour> 18 ) {
        return clearSky[1];
      }else
        return clearSky[0];
    }
    return codetoPicture[id];
  }

  String getWeatherInfo(String city,String field){
    Weather weather = data.searchWeather(cityName: city);
    if(weather != null){
      switch(field){
        case 'temperature':
          return weather.temperature;
        case 'pressure':
          return weather.pressure;
        case 'humidity':
          return weather.humidity;
        case 'weather description':
          return weather.weatherDescription;
        case 'wind speed':
          return weather.windSpeed;
        case 'feels_like':
          return weather.feelsLike;
      }
    }
    return "null";
  }

  IconData getWeatherIcon(String city){
    Weather weather = data.searchWeather(cityName: city);
    if(weather != null)
      return weather.icon;
    else
      return WeatherIcons.refresh;
  }
}

还有一个 listView.Builder 可以添加这些图块(城市小部件):

class CitiesScreen extends StatelessWidget {
  final TextEditingController _textEditingController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: NavigationBar(),backgroundColor: Colors.lightBlue,body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.symmetric(vertical: 20,horizontal: 10),child: Column(
            children: <Widget>[
              ColorfulBox(
                ListTile(
                title: TextField(
                  controller: _textEditingController,style: TextStyle(fontSize: 20,color: Colors.white),),trailing: SizedBox(
                  width: 100,child: Row(
                    children: [
                      SizedBox(
                        width: 50,child: FlatButton(
                          child: Icon(Icons.add,size: 30,color: Colors.white,onpressed: () {
                              Provider.of<DataManager>(context,listen: false).addCityByName(_textEditingController.text);
                              _textEditingController.clear();
                          },SizedBox(
                        width: 50,child: FlatButton(
                            onpressed: () => Provider.of<DataManager>(context,listen: false).findWeatherByLocation(),child: Icon(Icons.location_on_outlined,)
                    ],SizedBox(height: 30,Expanded(
                child: Consumer<DataManager>(
                  builder: (context,data,child){
                    return ListView.builder(
                      shrinkWrap: true,scrollDirection: Axis.vertical,itemCount: Provider.of<DataManager>(context).cityNumbers(),itemBuilder: (context,index) => Provider.of<DataManager>(context).cityWidgets[index],);
                  },)
            ],);
  }

}

解决方法

插入

Provider.of<DataManager>(context);

构建函数。

它会在您调用 notifyListeners() 并更新 UI 时进行侦听。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。