【问题标题】:Flutter: FutureBuilder keeps flashingFlutter:FutureBuilder 不断闪烁
【发布时间】:2021-10-20 06:40:04
【问题描述】:

拨打setState()时遇到问题。

这是该问题的屏幕记录:https://cln.sh/ndL24t

如您所见,点击小部件会导致图片从加载到图片闪烁。

问题是因为我有两个未来,因此是未来的建设者。第一个未来返回将要显示的信息。第二个 future 根据仪表板上显示的条目的 id 返回图像。我有第一个未来的建设者得到文本未来。我将未来设置在initState() 以避免重复调用。然后我在initState() 中设置了另一个Future 变量,如下journalFuture.then(...)。我还有一个AnimatedContainer(),它在用户通过更改值并调用setState() 来点击或向上/取消时动画。我认为这是问题的原因,但我不知道如何解决。

这是我的代码:

  const JournalSummary({Key? key}) : super(key: key);

  @override
  _JournalSummaryState createState() => _JournalSummaryState();
}

class _JournalSummaryState extends State<JournalSummary> {
  final GlobalKey lottieKey = GlobalKey(debugLabel: 'Lottie Key');

  late Future<List<JournalEntryData>> journalFuture;
  Future? picturesFuture;

  late Color _shadowColor;
  double _blurRadius = 15;

  void _animateDown() {
    setState(() {
      _shadowColor = Theme.of(context).shadowColor.withOpacity(0.40);
      _blurRadius = 25;
    });
  }

  void _animateUp() {
    setState(() {
      _shadowColor = Theme.of(context).shadowColor.withOpacity(0.19);
      _blurRadius = 15;
    });
  }

  @override
  void initState() {
    super.initState();
    journalFuture = DatabaseService(uid: AuthService().getUser()!.uid)
        .getJournalEntries(limit: 10);

    journalFuture.then((entries) {
      if (entries.isNotEmpty) {
        entries
            .sort((JournalEntryData firstEntry, JournalEntryData secondEntry) {
          DateTime firstDate = DateTime.parse(firstEntry.date);
          DateTime secondDate = DateTime.parse(secondEntry.date);

          int feelingCmp = secondEntry.feeling.compareTo(firstEntry.feeling);

          if (feelingCmp != 0) return feelingCmp;
          return secondDate.compareTo(firstDate);
        });
      }

      picturesFuture = StorageService(AuthService().getUser()!.uid)
          .getPictures(entries[0].date);
    });
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _shadowColor = Theme.of(context).shadowColor.withOpacity(0.19);
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      color: Colors.transparent,
      child: FutureBuilder(
        future: journalFuture,
        builder: (context, entryFuture) {
          List<JournalEntryData> entries =
              (entryFuture.data as List<JournalEntryData>?) ?? [];

          if (entries.isNotEmpty) {
            entries.sort(
                (JournalEntryData firstEntry, JournalEntryData secondEntry) {
              DateTime firstDate = DateTime.parse(firstEntry.date);
              DateTime secondDate = DateTime.parse(secondEntry.date);

              int feelingCmp =
                  secondEntry.feeling.compareTo(firstEntry.feeling);

              if (feelingCmp != 0) return feelingCmp;
              return secondDate.compareTo(firstDate);
            });
          }

          return GestureDetector(
            onTap: () => AppTheme.homeNavkey.currentState!.pushReplacement(
              PageRouteBuilder(
                transitionDuration: Duration(milliseconds: 320),
                pageBuilder: (BuildContext context, Animation<double> animation,
                    Animation<double> secondaryAnimation) {
                  return Tasks(false);
                },
                transitionsBuilder: (BuildContext context,
                    Animation<double> animation,
                    Animation<double> secondaryAnimation,
                    Widget child) {
                  return Align(
                    child: FadeTransition(
                      opacity: animation,
                      child: child,
                    ),
                  );
                },
              ),
            ),
            onTapDown: (_) => _animateDown(),
            onTapUp: (_) => _animateUp(),
            onTapCancel: () => _animateUp(),
            child: AnimatedContainer(
              duration: const Duration(milliseconds: 200),
              margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 25),
              padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 10),
              clipBehavior: Clip.hardEdge,
              decoration: BoxDecoration(
                color: Theme.of(context).backgroundColor,
                borderRadius: BorderRadius.circular(15),
                boxShadow: [
                  BoxShadow(
                    color: _shadowColor,
                    blurRadius: _blurRadius,
                  ),
                ],
              ),
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 5),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      mainAxisSize: MainAxisSize.max,
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        SvgPicture.asset(
                          'assets/adobe/illustrator/icons/svg/journal_selected.svg',
                          width: 35,
                          height: 35,
                        ),
                        SizedBox(width: 8),
                        Text(
                          entryFuture.data == null
                              ? 'Journal'
                              : _formatedDate(entries[0].date),
                          maxLines: 1,
                          overflow: TextOverflow.ellipsis,
                          style: Theme.of(context)
                              .textTheme
                              .subtitle2!
                              .copyWith(color: Theme.of(context).primaryColor),
                        ),
                        Spacer(),
                        (entryFuture.data == null)
                            ? Container()
                            : Lottie.asset(
                                'assets/lottie/faces/${(entries[0].feeling == 1 ? 'sad' : (entries[0].feeling == 2 ? 'meh' : 'happy'))}.json',
                                key: lottieKey,
                                repeat: false,
                                width: 50,
                                height: 50,
                              ),
                      ],
                    ),
                    SizedBox(height: 10),
                    FutureBuilder(
                      key: UniqueKey(),
                      future: picturesFuture,
                      initialData: [],
                      builder: (context, picFuture) {
                        return (picFuture.connectionState ==
                                    ConnectionState.waiting ||
                                picturesFuture == null)
                            ? Center(child: CircularProgressIndicator())
                            : SizedBox(
                                width:
                                    MediaQuery.of(context).size.width - 40 - 50,
                                height: 160,
                                child: ListView(
                                  scrollDirection: Axis.horizontal,
                                  clipBehavior: Clip.none,
                                  children: _buildPictures(
                                      (picFuture.data as List<Uint8List>)),
                                ),
                              );
                      },
                    ),
                    SizedBox(height: 10),
                    (entryFuture.data == null)
                        ? Container()
                        : Text(
                            entries[0].entryText,
                            style: Theme.of(context).textTheme.bodyText2,
                            maxLines: 3,
                            overflow: TextOverflow.ellipsis,
                          ),
                  ],
                ),
              ),
            ),
          );
        },
      ),
    );
  }

  List<Widget> _buildPictures(List<Uint8List> pictures) {
    List<Widget> picWidgets = [];
    int index = 0;
    for (var pic in pictures) {
      picWidgets.add(
        Container(
          key: UniqueKey(),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(10),
            boxShadow: [
              BoxShadow(
                blurRadius: 6,
                color: Theme.of(context).shadowColor.withOpacity(0.52),
                offset: Offset(0, 3),
              )
            ],
          ),
          clipBehavior: Clip.hardEdge,
          margin: index == 0
              ? EdgeInsets.only(right: 10)
              : EdgeInsets.symmetric(horizontal: 10),
          child: Image.memory(
            pic,
            key: UniqueKey(),
            height: 160,
            fit: BoxFit.cover,
          ),
        ),
      );
      index += 1;
    }
    return picWidgets;
  }

  String _formatedDate(String date) {
    DateTime dateTime = DateTime.parse(date);
    Map<int, String> _monthNumToName = {
      1: 'Jan',
      2: 'Feb',
      3: 'Mar',
      4: 'Apr',
      5: 'May',
      6: 'Jun',
      7: 'Jul',
      8: 'Aug',
      9: 'Sep',
      10: 'Oct',
      11: 'Nov',
      12: 'Dec',
    };

    return '${_monthNumToName[dateTime.month]} ${dateTime.day}, ${dateTime.year}';
  }
}

【问题讨论】:

  • 在真机上试用...或连接并使用编辑器运行...问题可能出在模拟器的性能上...
  • 在 PicturesFuture 的 FutureBuilder 中尝试移除 uniqueKey
  • 现在可以使用了。我不确定是什么解决了这个问题,就像我同时做了几件事一样。我跑了flutter upgrade,因为我提出这个问题后发布了一个新版本。我还稍微更改了代码,但在升级之前似乎没有修复它,所以很可能是flutter upgrade

标签: flutter dart stateful statefulwidget


【解决方案1】:

成功了。正如我在评论中提到的,我在发布问题后运行flutter upgrade,因为发布问题后出现了新版本,并且还稍微更改了代码,所以我不确定是什么解决了问题。也可能是我停止运行然后再次运行应用程序。

【讨论】:

    猜你喜欢
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-03
    • 2016-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多