简体   繁体   English

Flutter 提供程序错误:当继承的小部件更改时

[英]Flutter provider error: When an inherited widget changes

I don't think I'm dealing with providers very well.我不认为我与供应商打交道很好。 What is the correct code?什么是正确的代码?

**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();
}
}

The error message is like this.错误信息是这样的。

When an inherited widget changes, for example if the value of Theme.of() changes, its dependent widgets are rebuilt.当继承的小部件发生变化时,例如,如果 Theme.of() 的值发生变化,则重新构建其依赖的小部件。 If the dependent widget's reference to the inherited widget is in a constructor or an initState() method, then the rebuilt dependent widget will not reflect the changes in the inherited widget.如果依赖小部件对继承小部件的引用在构造函数或 initState() 方法中,则重建的依赖小部件将不会反映继承小部件中的更改。

Typically references to inherited widgets should occur in widget build() methods.通常,对继承的小部件的引用应该出现在小部件 build() 方法中。 Alternatively, initialization based on inherited widgets can be placed in the didChangeDependencies method, which is called after initState and whenever the dependencies change thereafter.或者,可以将基于继承的小部件的初始化放在 didChangeDependencies 方法中,该方法在 initState 之后以及此后依赖关系发生变化时调用。

The relevant error-causing widget was相关的导致错误的小部件是
MaterialApp材料应用
lib/main.dart:15 lib/main.dart:15
When the exception was thrown, this was the stack抛出异常时,这是堆栈

This is the code that uses this provider.这是使用此提供程序的代码。

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)),
  )
  );
 }
 }

sorry for my slow reply but I believe the below is how you should be structuring your screen.抱歉我的回复很慢,但我相信以下是您应该如何构建屏幕的方式。 The error is coming from the fact that there is no defined provider called UpdateWeather in your widget tree above LocationScreen so you need to define one using ChangeNotifierProvider .该错误来自这样一个事实,即在LocationScreen上方的小部件树中没有定义名为UpdateWeather的提供程序,因此您需要使用ChangeNotifierProvider定义一个。 (You can also use other providers but by looking at UpdateWeather it feels like ChangeNotifierProvider is a good fit.) Then you can add a Consumer of type UpdateWeather below the provider and it will automatically rebuild the screen when notifyListeners() is called in UpdateWeather . (您也可以使用其他提供程序,但通过查看UpdateWeather感觉ChangeNotifierProvider非常适合。)然后您可以在提供程序下方添加一个UpdateWeather类型的Consumer ,当在 UpdateWeather 中调用UpdateWeather notifyListeners()时,它将自动重建屏幕。

Please note the use of darts .. operator in the create call of ChangeNotifierProvider which ensures the updateUI method is called as the screen is built.请注意在ChangeNotifierProvidercreate调用中使用了 darts ..运算符,它确保在构建屏幕时调用updateUI方法。 This also allows us to make the whole screen stateless as the provider handles changes to state now.这也使我们能够使整个屏幕无状态,因为提供程序现在处理对 state 的更改。

Additionally you can also replace all the Provider.of<UpdateWeather>() references with weather as the provider is returned by the Consumer<UpdateWeather> .此外,您还可以将所有Provider.of<UpdateWeather>()引用替换为weather ,因为提供者由Consumer<UpdateWeather>返回。

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)),
            )),
      ),
    );
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Flutter 使用 Provider 时出现“EditableText 上方不存在覆盖小部件”错误 - Flutter 'No Overlay widget exists above EditableText' error when using Provider 请解释语法 - flutter bloc 提供程序使用继承的小部件 - Please Explain syntax - flutter bloc provider using inherited widget Flutter Provider:为什么调用Provider.of时会出现这个错误<widget> (上下文)像 tihis:</widget> - Flutter Provider: Why does this error happens when calling Provider.of<Widget>(context) like tihis: Flutter:继承的小部件和路由 - Flutter: Inherited Widget and Routes Flutter:继承的小部件 - Flutter: inherited widget Flutter:Connectivity Widget Wrapper Provider 错误 - Flutter: Connectivity Widget Wrapper Provider error Flutter 线图小部件未使用更改通知程序在提供者的数据更改上重建 - Flutter Linechart Widget not rebuilding on Data Changes with Provider using Change Notifier Flutter 中的提供程序出现错误“无法在此 X Widget 上方找到正确的提供程序” - Provider in Flutter with error "Could not find the correct provider above this X Widget" 颤振提供者错误:在此小部件上方找不到正确的提供者 - flutter provider error : Could not find the correct provider above this widget Flutter - 当 Provider 变量改变时触发导航 - Flutter - trigger navigation when Provider variable changes
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM