0

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. 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.

Typically references to inherited widgets should occur in widget build() methods. Alternatively, initialization based on inherited widgets can be placed in the didChangeDependencies method, which is called after initState and whenever the dependencies change thereafter.

The relevant error-causing widget was
MaterialApp
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)),
  )
  );
 }
 }
David K
  • 3,147
  • 2
  • 13
  • 19
hyesujo
  • 1
  • 1
  • 3

1 Answers1

0

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. (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.

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. This also allows us to make the whole screen stateless as the provider handles changes to state now.

Additionally you can also replace all the Provider.of<UpdateWeather>() references with weather as the provider is returned by the 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)),
            )),
      ),
    );
  }
}