Ошибка провайдера Flutter: при изменении унаследованного виджета - PullRequest
0 голосов
/ 17 июня 2020

Я не думаю, что хорошо общаюсь с провайдерами. Какой правильный код?

**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 (), то перестроенный зависимый виджет не будет отражать изменения в унаследованном виджете.

Обычно ссылки на унаследованные виджеты должны встречаться в виджете build () методы. В качестве альтернативы инициализация на основе унаследованных виджетов может быть помещена в метод didChangeDependencies, который вызывается после initState и всякий раз, когда после этого зависимости изменяются. .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)),
  )
  );
 }
 }

1 Ответ

0 голосов
/ 17 июня 2020

извините за медленный ответ, но я считаю, что ниже показано, как вы должны структурировать свой экран. Ошибка возникает из-за того, что в дереве виджетов выше LocationScreen нет определенного провайдера с именем UpdateWeather, поэтому вам нужно определить его, используя ChangeNotifierProvider. (Вы также можете использовать других провайдеров, но, глядя на UpdateWeather, кажется, что ChangeNotifierProvider подходит.) Затем вы можете добавить Consumer типа UpdateWeather под провайдером, и он автоматически перестроит экран, когда notifyListeners() вызывается в UpdateWeather.

Обратите внимание на использование оператора darts .. в вызове create из ChangeNotifierProvider, который обеспечивает вызов метода updateUI при построении экрана. Это также позволяет нам сделать весь экран без состояния, поскольку поставщик обрабатывает изменения состояния сейчас.

Кроме того, вы также можете заменить все ссылки 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)),
            )),
      ),
    );
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...