【问题标题】:Flutter provider error: When an inherited widget changesFlutter 提供程序错误:当继承的小部件更改时
【发布时间】:2020-10-07 03:54:38
【问题描述】:

我认为我与供应商打交道不是很好。什么是正确的代码?

**import 'package:flutter/material.dart';
import 'package:geo_app/model/wether.dart';**

class UpdateWeather extends ChangeNotifier{

WeatherModel weathers = WeatherModel();
int temperature;
dynamic weatherImage;
String city;
dynamic weatherBack;


Future<void> updateUi(dynamic weatherData) async {
double temp =await weatherData['main']['temp'].toDouble();
 temperature = temp.toInt();
 var condition =await weatherData['weather'][0]['id'];
weatherBack = weathers.getWBackgroundImage(condition);
weatherImage = weathers.getWeatherImage(condition);
city = weatherData['name'];
notifyListeners();
}
}

错误信息是这样的。

当继承的小部件发生更改时,例如,如果 Theme.of() 更改,其依赖的小部件被重建。如果 依赖小部件对继承小部件的引用位于 构造函数或 initState() 方法,然后重建依赖 小部件不会反映继承小部件中的更改。

通常对继承的小部件的引用应该出现在小部件中 构建()方法。或者,基于继承的初始化 小部件可以放在 didChangeDependencies 方法中,即 在 initState 之后以及依赖项发生变化时调用 之后。

相关的导致错误的小部件是
MaterialApp
lib/main.dart:15
抛出异常时,这是堆栈

这是使用此提供程序的代码。

import 'package:flutter/material.dart';
import 'package:geo_app/Provider/update_wearher.dart';
import 'package:geo_app/const.dart';
import 'package:geo_app/model/wether.dart';
import 'package:geo_app/view/navigator_dawer.dart';
import 'package:provider/provider.dart';

class LocationScreen extends StatefulWidget {
static const routeName = '/lacation';

final locationWeather;

const LocationScreen({Key key, this.locationWeather}) : super(key: 
key);
@override
_LocationScreenState createState() => _LocationScreenState();
}

class _LocationScreenState extends State<LocationScreen> {
WeatherModel weathers = WeatherModel();

@override
void initState() {
 super.initState();
 Provider.of<UpdateWeather> 
(context).updateUi(widget.locationWeather);
}

@override
void setState(fn) {
Provider.of<UpdateWeather> 
(context).updateUi(widget.locationWeather);
super.setState(fn);
 }

@override
Widget build(BuildContext context) {

return Scaffold(
  body:Stack(children: <Widget>[
  Container(
      decoration: BoxDecoration(
        color: Colors.grey[850],
        image: DecorationImage(
            image: AssetImage(Provider.of<UpdateWeather> 
     (context).weatherBack),
            colorFilter:  ColorFilter.mode(
                Colors.black.withOpacity(0.5), BlendMode.dstATop),
            fit: BoxFit.cover),
      ),
      constraints: BoxConstraints.expand(),
      padding: EdgeInsets.only(top : 200),
      child: Column(children: <Widget>[
         Image.asset(Provider.of<UpdateWeather> 
    (context).weatherImage,
            height: 120,
          width:120,
        ),
        // Image.asset(
        //   'assets/sun.png',
        //   alignment: Alignment.center,
        //   height: 120,
        //   width:120,
        // ),  
        SizedBox(height:30),
        Text('${Provider.of<UpdateWeather>(context).temperature}°',
        style: ktextStyle,
        ),
        SizedBox(
          height:10
        ),
        Text('${Provider.of<UpdateWeather>(context).city}',
        style: ktextStyle,)
      ],
      ),
    ),
    Positioned(
      child:AppBar(
       actions: <Widget>[
         IconButton(icon: Icon(Icons.near_me),
          onPressed: () async {
            var weatherData = await weathers.getLocationWeather();
           Provider.of<UpdateWeather>(context). 
  updateUi(weatherData);
          })
       ],
    backgroundColor: Colors.transparent,
    elevation: 0,
  ),)
  ],
  ),
  drawer: Theme(child: NavigatorDrawer(),
    data: Theme.of(context).
    copyWith(canvasColor: Colors.blueGrey.withOpacity(0.2)),
  )
  );
 }
 }

【问题讨论】:

  • 嗨@hyesujo,从您的错误消息看来,UpdateWeather 提供程序可能在您代码中的错误位置初始化,您能否发布使用此提供程序的代码?
  • @giles-correia-morton tank你我上传了代码
  • @giles-correia-morton 非常感谢。下班后我会照你说的做的。

标签: flutter dart flutter-dependencies provider flutter-change-notifier


【解决方案1】:

对不起,我的回复很慢,但我相信以下是您应该如何构建屏幕的方式。错误来自这样一个事实,即在LocationScreen 上方的小部件树中没有定义名为UpdateWeather 的提供程序,因此您需要使用ChangeNotifierProvider 定义一个提供程序。 (您也可以使用其他提供程序,但通过查看UpdateWeather,感觉ChangeNotifierProvider 很合适。)然后您可以在提供程序下方添加UpdateWeather 类型的Consumer,它会自动重建屏幕notifyListeners()UpdateWeather 中调用。

请注意在ChangeNotifierProvidercreate 调用中使用飞镖.. 运算符,以确保在构建屏幕时调用updateUI 方法。这也允许我们在提供程序处理状态更改时使整个屏幕无状态。

此外,您还可以将所有 Provider.of&lt;UpdateWeather&gt;() 引用替换为 weather,因为提供程序由 Consumer&lt;UpdateWeather&gt; 返回。

import 'package:flutter/material.dart';
import 'package:geo_app/Provider/update_wearher.dart';
import 'package:geo_app/const.dart';
import 'package:geo_app/model/wether.dart';
import 'package:geo_app/view/navigator_dawer.dart';
import 'package:provider/provider.dart';

class LocationScreen extends StatelessWidget {
  static const routeName = '/lacation';
  final locationWeather;
  final WeatherModel weathers = WeatherModel();

  LocationScreen({Key key, this.locationWeather});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<UpdateWeather>(
      create: (context) => UpdateWeather()..updateUi(locationWeather),
      child: Consumer<UpdateWeather>(
        builder: (context, weather, _) => Scaffold(
            body: Stack(
              children: <Widget>[
                Container(
                  decoration: BoxDecoration(
                    color: Colors.grey[850],
                    image: DecorationImage(
                        image: AssetImage(weather.weatherBack),
                        colorFilter: ColorFilter.mode(
                            Colors.black.withOpacity(0.5), BlendMode.dstATop),
                        fit: BoxFit.cover),
                  ),
                  constraints: BoxConstraints.expand(),
                  padding: EdgeInsets.only(top: 200),
                  child: Column(
                    children: <Widget>[
                      Image.asset(
                        weather.weatherImage,
                        height: 120,
                        width: 120,
                      ),
                      // Image.asset(
                      //   'assets/sun.png',
                      //   alignment: Alignment.center,
                      //   height: 120,
                      //   width:120,
                      // ),
                      SizedBox(height: 30),
                      Text(
                        '${weather.temperature}°',
                        style: ktextStyle,
                      ),
                      SizedBox(height: 10),
                      Text(
                        '${weather.city}',
                        style: ktextStyle,
                      )
                    ],
                  ),
                ),
                Positioned(
                  child: AppBar(
                    actions: <Widget>[
                      IconButton(
                          icon: Icon(Icons.near_me),
                          onPressed: () async {
                            var weatherData =
                                await weathers.getLocationWeather();
                            weather.updateUi(weatherData);
                          })
                    ],
                    backgroundColor: Colors.transparent,
                    elevation: 0,
                  ),
                )
              ],
            ),
            drawer: Theme(
              child: NavigatorDrawer(),
              data: Theme.of(context)
                  .copyWith(canvasColor: Colors.blueGrey.withOpacity(0.2)),
            )),
      ),
    );
  }
}

【讨论】:

    猜你喜欢
    • 2021-10-12
    • 2021-08-17
    • 2021-01-21
    • 2021-11-22
    • 2020-07-15
    • 1970-01-01
    • 2018-10-02
    • 2020-07-21
    • 2020-09-18
    相关资源
    最近更新 更多