首页 > 解决方案 > 提供者状态管理实施。将函数放入 create: property

问题描述

我完全迷失在状态管理领域。尝试了多个教程、文章,甚至查看了 Github 类似的项目。不知道如何在我的天气应用程序中实现提供程序。

class WeatherMainScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: kBackgroundColor,
      child: SafeArea(
        child: ChangeNotifierProvider<WeatherModel>(
          create: (context) => ApiCall().getWeather('New York'),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              Container(
                margin: EdgeInsets.only(
                  bottom: 30,
                  top: 15,
                  left: 30,
                  right: 30,
                ),
                child: Column(
                  children: <Widget>[
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        Text(
                          'Today 28. apr',
                          style: TextStyle(
                            color: kAccentColor,
                            fontSize: 18,
                            fontWeight: FontWeight.w400,
                          ),
                        ),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.end,
                          children: <Widget>[
                            MenuSearchButton(
                              boxSize: 60,
                              onPressed: () => print('search prssed'),
                              content: Icon(
                                Icons.search,
                                color: Colors.white,
                                size: 30,
                              ),
                            ),
                            MenuSearchButton(
                              boxSize: 60,
                              onPressed: () => print('menu pressed'),
                              content: Icon(
                                Icons.menu,
                                color: Colors.white,
                                size: 30,
                              ),
                            ),
                          ],
                        ),
                      ],
                    ),
                    Container(
                      padding: EdgeInsets.symmetric(vertical: 20.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          Text(
                            '12',
                            style: TextStyle(
                              color: Colors.white,
                              fontSize: 100,
                            ),
                          ),
                          Container(
                            padding: EdgeInsets.only(left: 10.0),
                            child: Row(
                              children: <Widget>[
                                Icon(
                                  Icons.cloud,
                                  color: Colors.white,
                                  size: 25.0,
                                ),
                                SizedBox(width: 15.0),
                                Text(
                                  'Raining',
                                  style: TextStyle(
                                    color: Colors.white,
                                    fontSize: 18,
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
              Column(
                children: <Widget>[
                  Container(
                    margin: EdgeInsets.only(
                      bottom: 30,
                      top: 15,
                      left: 60,
                      right: 60,
                    ),
                    child: Text(
                      'Put on your coat, and don\'t forget the umbrella.',
                      textAlign: TextAlign.center,
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 25,
                      ),
                    ),
                  ),
                  Divider(
                    color: kAccentColor,
                  ),
                  Container(
                    margin: EdgeInsets.only(
                      bottom: 30,
                      top: 15,
                      left: 30,
                      right: 30,
                    ),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: <Widget>[
                        DetailedCard(
                          header: 'HUMIDITY',
                          headerColor: kAccentColor,
                          text: '87%',
                          textColor: Colors.white,
                        ),
                        DetailedCard(
                          header: 'WIND M/S',
                          headerColor: kAccentColor,
                          text: '4,1',
                          textColor: Colors.white,
                        ),
                        DetailedCard(
                          header: 'FEELS LIKE',
                          headerColor: kAccentColor,
                          text: '18',
                          textColor: Colors.white,
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

所以我有一个模型类 WeatherModel 它基本上是空的,只包含天气信息的构造函数。ApiCall 类是所有网络发生的地方,它返回填充数据的 WeatherModel 对象。但是对于像这样的 ChangeNotifier,我会得到错误:'返回类型'Future'不是'WeatherModel',正如匿名闭包所定义的那样。'

我读到 ChangeNotifierProvider 在创建时应该只接收一个对象,而我正在向它传递一个函数。但我不知道还能在哪里调用该 getWeather 函数?完全迷失了。

编辑:

ApiCall.dart

class ApiCall extends ChangeNotifier{
  Future<WeatherModel> getWeather(String cityName) async {
    String url =
        'https://api.openweathermap.org/data/2.5/weather?q=$cityName&appid=$apikey';
    http.Response response = await http.get(url);

    if (response.statusCode == 200) {
      var weatherData = jsonDecode(response.body);

      return WeatherModel(
        temp: weatherData['main']['temp'] - 273.15,
        feelsLike: weatherData['main']['temp'] - 273.15,
        condition: weatherData['weather'][0]['main'],
        humidity: weatherData['main']['humidity'],
        windSpeed: weatherData['wind']['speed'],
      );
    } else {
      throw Exception('Ooops something went wrong');
    }
  }
}

天气模型.dart

class WeatherModel{
  final double temp;
  final double windSpeed;
  final int feelsLike;
  final int humidity;
  final String condition;

  WeatherModel({
    this.temp,
    this.windSpeed,
    this.feelsLike,
    this.humidity,
    this.condition,
  });
}

标签: flutterdart

解决方案


There are several change which you should make to work your code.

Change following line

    child: ChangeNotifierProvider<WeatherModel>(

To

    child: ChangeNotifierProvider< ApiCall >(

You have to provide class name which extends ChangeNotifier.

You have to call notifyListeners() at the end of method, on which call you want to change data.

  else {
      throw Exception('Ooops something went wrong');
    }
    notifyListeners();  // added line
  }

getWeather should not return any value. Instead of that you can create any WeatherModel object in ApiCall class and update it in that method and access that object wherever you want to use that data.

Update:

 child: ChangeNotifierProvider<ApiCalll>( create: (context) => ApiCall()

You can call this method in following way.

Provider.of<ApiCall>(context).getWeather('New York');

推荐阅读