首页 > 解决方案 > 我可以将 setState 仅用于一个小部件而不是整个页面吗?

问题描述

我有一个 Future,它从我的 Cloud Firestore 数据库中获取一个值,并在我的应用程序正文中显示一个图标。如果数据库中的值发生更改,则图标会更新。我一直在使用 setState 来重建我的小部件树,并且效果很好 - 该应用程序几乎可以立即对我的 Cloud Firestore 数据库中的更改做出反应。这很棒!代码:

Future<void> takenSurvey2() async {
 final sn = await Firestore.instance
 .collection('Controller')
      .document('Current Survey')
      .get();
 surveyName2 = sn['cs'];
 final snapShot = await Firestore.instance
 .collection('$surveyName2' + '_entrants')
      .document(userid)
      .get();
 if (snapShot.exists) {
 takenSurvey = true;
  } else {
 takenSurvey = false;
  }
  setState(() {});
}

并且显示图标的位置编码如下(在堆栈内):

Positioned(
    right: 30,
    top: 20,
    child: FutureBuilder(
        future: takenSurvey2(),
        builder: (context, snapshot) {
 if (takenSurvey == false) {
 return Icon(
              Foundation.burst_new,
              size: 48,
              color: Color(0xff303841),
            );
          } else if (takenSurvey == true) {
 return Icon(
              Foundation.check,
              size: 48,
              color: Color(0xff303841),
            );
          } else
            return Container();
        })),

但是,我使用“admob_flutter”包在我的 AdMob 广告中添加了,因为 setState 似乎一直在运行,所以广告无法加载 - 我只看到一个闪烁的框。如果我从上面的代码中删除 setState,则广告会加载,但当 Cloud Firestore 中的值更改时,我的应用程序中的图标不会更新。

如何从 setState 中排除我的 admob_flutter 小部件,或者仅使用 setState(或其他东西)来仅更新我的 FutureBuilder 小部件?我想以限制 Cloud Firestore 上的调用次数的方式这样做,但这不是必需的。

我尝试过使用嵌套条件逻辑,但它似乎不起作用!

谢谢!

标签: flutterdartgoogle-cloud-firestore

解决方案


我可以建议你使用ValueNotifier,如果你想操作简单的数据,比如在这种情况下是一个布尔值,这个小部件可以是完美的。您也可以使用 avoid function而不是 a future,如下所示:

  // Add a ValueNotifier for a single value
  final ValueNotifier<bool> _takenSurvey = ValueNotifier(null);

  void takenSurvey2() async {
    final sn = await Firestore.instance
        .collection('Controller')
        .document('Current Survey')
        .get();
    surveyName2 = sn['cs'];
    final snapShot = await Firestore.instance
        .collection('$surveyName2' + '_entrants')
        .document(userid)
        .get();
    if (snapShot.exists) {
      // Update the value of the ValueNotifier 
      _takenSurvey.value = true;
    } else {
      _takenSurvey.value = false;
    }
  }

并使用ValueListenableBuilder监听该值的变化:

Positioned(
  right: 30,
  top: 20,
  child: ValueListenableBuilder(
    valueListenable: _takenSurvey,
    builder: (context, takenSurvey, child) {
      if(takenSurvey == null){
        return Container();
      }
      else{
        if (takenSurvey == false) {
          return Icon(
            Foundation.burst_new,
            size: 48,
            color: Color(0xff303841),
          );
        } else {
          return Icon(
            Foundation.check,
            size: 48,
            color: Color(0xff303841),
          );
        } 
      }
    },
  ),
)

希望能帮助到你。


推荐阅读