[英]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:15lib/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.请注意在
ChangeNotifierProvider
的create
调用中使用了 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.