【问题标题】:Second screen doesn't appear until initState is done在完成 initState 之前不会出现第二个屏幕
【发布时间】:2021-01-18 12:13:04
【问题描述】:

我有 StatefulWidget,它的 initState() 触发异步 onInit() 函数,该函数触发返回项目列表的顶级函数,然后 onInit 填充项目列表。 然后我有 Scaffold 哪个 body 应该返回 CircularProgressIndicator 直到 items == null 然后 Column 与项目。

问题是我点击按钮导航到第二个屏幕,直到屏幕出现大约需要 3-4 秒,当它出现时,列表被填充。我很确定该功能在完成之前不会让屏幕出现,但我不知道为什么?

如果它应该导航到第二个屏幕然后启动 initState 并显示加载指示器直到函数完成,为什么会出现这种行为?

谁能帮帮我,好吗?

【问题讨论】:

    标签: flutter dart statefulwidget


    【解决方案1】:

    你是在 iOS 上测试这个吗? 自从 Apple 弃用 OpenGL 以来,Flutter 就遇到了 Metal 引擎上的 Shader Caching 问题。

    https://github.com/flutter/flutter/issues/32170

    您第二次使用的是 FutureBuilder 吗? 接下来,对于需要从某个数据源加载信息并且必须让用户等待的所有操作,请确保使用 FutureBuilder 小部件。 https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html 始终使用未来的构建器来避免任何延迟,任何你可以异步的东西,都这样做。 以下是来自 Flutter 团队的一些性能提示的链接: https://flutter.dev/docs/perf/rendering/best-practices

    我为您编写了一个小实现,以演示如何实现您正在寻找的内容。

    Future<List<String>> loadItemsFromSource;
    @override
    void initState() {
      super.initState();
        
      loadItemsFromSource = doSomeLogic();
      }
    
    Future<List<String>> doSomeLogic(){
    
       //Read the results from the top level function
       //then return the results here
    
       return topLevelFunction(); //returns a list of Strings
    }
        
        
    @override
    Widget build(BuildContext context) {
       return FutureBuilder<List<String>>(
              future: loadItemsFromSource,
              builder: (context, state) {
                if (state.connectionState == ConnectionState.active ||
                   state.connectionState == ConnectionState.waiting) {
                     return Center(
                             child: CircularProgressIndicator(
                                    backgroundColor: Colors.black,
                                    valueColor: new AlwaysStoppedAnimation<Color> 
                                    (Colors.orange),
                           ));
                      } else {
    
        //return a ListView of your results
                return new ListView.builder(
                      itemBuilder: (item, index) {
                        return Container(child: Text(state.data[index]));
                      },
                      itemCount: state.data.length);
                }
            });
        }
    

    【讨论】:

    • 是的,我正在测试。它在 iOS 上。感谢您的回答,我会在一个小时左右看看,如果它工作正常,请告诉您。
    • 如果这能解决您的问题,请务必点赞。这将帮助我,帮助更多的人。谢谢
    • 抱歉,这不起作用。首先,我在 Android 上尝试了它,它是相同的,甚至更糟。然后只需重写代码以使用 FutureBuilder 并在顶级功能完成后出现相同的屏幕。
    • 在这种情况下,您需要使用 dart:async 包中提供的 RestartableTimer 类。
    • 此计时器将运行 2 秒,它将使布尔属性为真。此布尔属性确保将其添加到 futureBuilder 的 if 条件中。一旦计时器完成,则该属性设置为 true,并且允许未来的构建器渲染 ui 的其余部分
    【解决方案2】:

    在这种情况下,因为我在 initState() 上触发的函数进行了一些繁重的计算,并且因为 Dart 是单线程语言,并且因为 CPU 与 I/O 分离,所以它开始计算,直到函数完成它才构建小部件。

    因此我选择使用隔离!

    【讨论】:

      猜你喜欢
      • 2021-12-12
      • 1970-01-01
      • 2016-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多