Как остановить перезагрузку виджета в методе setState () в классе StatefulWidget во Flutter

Я пытаюсь сохранить состояние виджета, т.е. он не должен обновляться при вызове метода setState ().

class _GenderSelectionPageState extends State<GenderSelectionPage> {
  bool isFemaleSelected = false;
  AdmobBannerSize bannerSize;
  GlobalKey _globalKey = new GlobalKey();

  bool isLoaded = false;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    bannerSize = AdmobBannerSize.BANNER;
  }

  @override
  Widget build(BuildContext context) {
    double height = MediaQuery.of(context).size.height;
    double width = MediaQuery.of(context).size.width;

    return new Scaffold(
      body: new Container(
          width: width,
          child: new Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.end,
              children: <Widget>[
                Expanded(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    mainAxisSize: MainAxisSize.max,
                    children: <Widget>[
                      Flexible(
                        child: new Hero(
                          tag: "gender",
                          child: Material(
                            child: new Row(
                              children: <Widget>[
                                InkWell(
                                  onTap: () {
                                    setState(() {
                                      if (isFemaleSelected) {
                                        isFemaleSelected = false;
                                      } else {
                                        isFemaleSelected = true;
                                      }
                                    });
                                  },
                                  child: Opacity(
                                    child: Image.asset(
                                      "assets/woman.png",
                                      height: height / 4,
                                      width: width / 2 - 12,
                                    ),
                                    opacity: isFemaleSelected ? 1.0 : 0.30,
                                  ),
                                ),
                                InkWell(
                                  onTap: () {
                                    setState(() {
                                      if (isFemaleSelected) {
                                        isFemaleSelected = false;
                                      } else {
                                        isFemaleSelected = true;
                                      }
                                    });
                                  },
                                  child: Opacity(
                                    opacity: !isFemaleSelected ? 1.0 : 0.30,
                                    child: Image.asset(
                                      "assets/boy.png",
                                      height: height / 4,
                                      width: width / 2 - 12,
                                    ),
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                  flex: 1,
                ),
                InkWell(
                    onTap: () {
                      setState(() {

                      });
                      Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (BuildContext) =>
                                  new HeightWeightSelection(isFemaleSelected
                                      ? "assets/woman.png"
                                      : "assets/boy.png")));
                    },
                    child: Container(
                      margin: EdgeInsets.only(bottom: 12.0),
                      child: new Image.asset(
                        "assets/next.png",
                        height: 64.0,
                        width: 64.0,
                      ),
                    )),
                new AdmobBannerWrapper(adUnitId: getBannerAdUnitId(),adSize: bannerSize,key: _globalKey,),
               /* new AdmobBanner(
                  adUnitId: getBannerAdUnitId(),
                  adSize: bannerSize,
                  listener:
                      (AdmobAdEvent event, Map<String, dynamic> args) {
                    handleEvent(event, args, 'Banner');
                  },
                ),*/
              ],
            ),
          )),
    );
  }

Я не хочу вызывать AdmobBannerWrapper каждый раз, когда нажимаю кнопку с изображением внизу. AdmobBannerWrapper должен загружаться только один раз, но дело в том, что всякий раз, когда я нажимаю на следующее изображение, он загружает метод AdmobBannerWrapper каждый раз.


person Hitesh Danidhariya    schedule 24.02.2020    source источник
comment
если вы не хотите снова перестраивать AdmobBannerWrapper, переместите этот виджет в родительский виджет.   -  person Darish    schedule 24.02.2020
comment
Спасибо, Дариш, но мой родительский виджет - это столбец, завернутый в Scaffold класса Statefull.   -  person Hitesh Danidhariya    schedule 24.02.2020
comment
непонятно, почему вы хотите сохранить AdmobBannerWrapper в дочернем виджете. Не могли бы вы объяснить свой вариант использования?   -  person Darish    schedule 24.02.2020
comment
Подождите, я загружу весь свой класс, чтобы вы могли лучше его понять.   -  person Hitesh Danidhariya    schedule 24.02.2020
comment
(adUnitId: getBannerAdUnitId() не делай этого. Вы можете прочитать https://stackoverflow.com/questions/52249578/how-to-deal-with-unwanted-widget-build   -  person Rémi Rousselet    schedule 24.02.2020


Ответы (2)


Создайте его в initState(), а затем используйте его ссылку везде, где требуется, он не будет строиться снова, пока родительский виджет не будет повторно инициализирован.

  var banner;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    bannerSize = AdmobBannerSize.BANNER;
    banner = AdmobBannerWrapper(adUnitId: getBannerAdUnitId(),adSize: bannerSize,key:_globalKey,);
  }

чем называть это по ссылке здесь banner


  @override
  Widget build(BuildContext context) {
    double height = MediaQuery.of(context).size.height;
    double width = MediaQuery.of(context).size.width;

    return new Scaffold(
      body: new Container(
          width: width,
          child: new Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.end,
              children: <Widget>[
                Expanded(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    mainAxisSize: MainAxisSize.max,
                    children: <Widget>[
                      Flexible(
                        child: new Hero(
                          tag: "gender",
                          child: Material(
                            child: new Row(
                              children: <Widget>[
                                InkWell(
                                  onTap: () {
                                    setState(() {
                                      if (isFemaleSelected) {
                                        isFemaleSelected = false;
                                      } else {
                                        isFemaleSelected = true;
                                      }
                                    });
                                  },
                                  child: Opacity(
                                    child: Image.asset(
                                      "assets/woman.png",
                                      height: height / 4,
                                      width: width / 2 - 12,
                                    ),
                                    opacity: isFemaleSelected ? 1.0 : 0.30,
                                  ),
                                ),
                                InkWell(
                                  onTap: () {
                                    setState(() {
                                      if (isFemaleSelected) {
                                        isFemaleSelected = false;
                                      } else {
                                        isFemaleSelected = true;
                                      }
                                    });
                                  },
                                  child: Opacity(
                                    opacity: !isFemaleSelected ? 1.0 : 0.30,
                                    child: Image.asset(
                                      "assets/boy.png",
                                      height: height / 4,
                                      width: width / 2 - 12,
                                    ),
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                  flex: 1,
                ),
                InkWell(
                    onTap: () {
                      setState(() {

                      });
                      Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (BuildContext) =>
                                  new HeightWeightSelection(isFemaleSelected
                                      ? "assets/woman.png"
                                      : "assets/boy.png")));
                    },
                    child: Container(
                      margin: EdgeInsets.only(bottom: 12.0),
                      child: new Image.asset(
                        "assets/next.png",
                        height: 64.0,
                        width: 64.0,
                      ),
                    )),
                banner, /*this is our variable */
               /* new AdmobBanner(
                  adUnitId: getBannerAdUnitId(),
                  adSize: bannerSize,
                  listener:
                      (AdmobAdEvent event, Map<String, dynamic> args) {
                    handleEvent(event, args, 'Banner');
                  },
                ),*/
              ],
            ),
          )),
    );
  }
person Vrushi Patel    schedule 25.02.2020
comment
Да сделал то же самое пока. Спасибо :) - person Hitesh Danidhariya; 25.02.2020
comment
Есть идеи о том, как использовать ключи для этого? - person Hitesh Danidhariya; 25.02.2020
comment
Ключи здесь не помогут, если родительский виджет построит его по умолчанию и перестроит с ним потомков. - person Vrushi Patel; 25.02.2020
comment
Ты настоящий герой !!! Большое спасибо. Это буквально спасает мою жизнь - person marlonjd; 10.05.2020
comment
Лучший подход! ... Работает отлично. Большое спасибо за этот ответ - person blessing dickson; 23.01.2021

Поместите его в виджет без сохранения состояния:

class AdBanner extends StatelessWidget{
  final adUnitId;
  final adSize;

  const AdBanner({Key key, this.adUnitId, this.adSize}) : super(key: key);

  Widget build(BuildContext context){
    return AdmobBannerWrapper(
      adUnitId: getBannerAdUnitId(),
      adSize: bannerSize,
      key: _globalKey,
      );
  }
}

в следующий раз, когда вы вызовете setState, если параметры не изменились, он не будет перестроен.

person aligator    schedule 24.02.2020
comment
Может ли этот виджет без сохранения состояния вызываться как часть иерархии дерева виджетов построения виджетов с сохранением состояния ?? - person K Pradeep Kumar Reddy; 10.09.2020