I have a widget that takes a long time to build and can't figure out how to show a loading spinner while it loads

huangapple go评论57阅读模式
英文:

I have a widget that takes a long time to build and can't figure out how to show a loading spinner while it loads

问题

Update 3: ok finally figured out that even if I get everything to build into a list of widgets async, when I go to display the widgets it hangs up. You’d think that listview would work since it should only load the items in view, but even that hangs and is slow to scroll.

第三次更新:好吧,最后我终于弄清楚了,即使我将所有内容都异步构建成小部件列表,当我尝试显示小部件时,它仍然会挂起。你可能认为ListView会有效,因为它只加载在视图中的项目,但即使是那样,它也会挂起并滚动缓慢。

Update 2: I deleted lines until I found that the single line that causes the delay (i.e. isn't run asynchronously no matter what I try) is this: criteriaRow.add(Row(...)). I've scoured the internet but it doesn't seem that adding things to a list can be done asynchronously. I must be doing something wrong...

第二次更新:我删除了一些行,直到我发现导致延迟的唯一行(即无论我尝试什么,都不能以异步方式运行)是这一行:criteriaRow.add(Row(...))。我搜索了互联网,但似乎无法异步添加内容到列表中。我一定是做错了什么...

I know how to run async functions and I can see how to use a FutureBuilder, but those are for when the data gathering itself is slow. In this case, I can build the lists and data I need very quickly. But, when I go to create the actual final widget, it takes around 4-5 seconds and hangs up the main thread. How can I build a widget asynchronously?

我知道如何运行异步函数,也知道如何使用FutureBuilder,但那些用于数据收集本身很慢的情况。在这种情况下,我可以非常快速地构建所需的列表和数据。但是,当我尝试创建实际的最终小部件时,它大约需要4-5秒钟,并会导致主线程挂起。如何异步构建小部件呢?

The clear problem is the for loops I have in the widget (see below). When I delete them, it loads quickly.

明显的问题在于小部件中的for循环(见下文)。当我删除它们时,加载速度很快。

Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flexible(
child: SingleChildScrollView(
child: Card(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [

                for(var i in displayRequired1) i,
                for(var i in displayRequired2) i,

              ],
            ),
          )
      ),
    )
),

],
);

UPDATE: more complete code (the complete code is way too long to add).

更多完整的代码(完整的代码太长了,无法添加)。

Function that initiates list generation:

启动列表生成的函数:

Future<String> solveCase() async {

display = displayType.summary;

// Parse studies early so data is available
List<ParseTest> ncsResult = [];

// Build required NCS
displayRequiredNCS.add(
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets all(5),
width: 200,
child: Text(
'Nerve Studies',
style: TextStyle(
fontSize: largeFontSize,
color: colorTextDefault,
fontWeight: FontWeight.normal
),
),
),
Expanded(
child: Container(
padding: EdgeInsets all(5),
child: Text(
'',
style: TextStyle(
fontSize: largeFontSize,
color: colorTextDefault,
fontWeight: FontWeight normal
),
),
),
),
],
),
);
print('NCS length: ${ncsResult.length}');
ncsResult.forEach((r) {
List<Widget> criteriaRow = [];
if(r.prettyCriteria[0] == '-' || r.prettyCriteria[0] == '+'){
r.prettyCriteria.split('\n').forEach((e) {
criteriaRow.add(Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Container(
padding: EdgeInsets all(5),
child: Text(
'${e.substring(1)}',
style: TextStyle(
fontSize: mediumFontSize,
color: colorTextDefault,
fontWeight: FontWeight normal
),
),
),
),
Container(
padding: EdgeInsets all(5),
alignment: Alignment center,
width: 200,
child: e[0] == '+' ? Icon(Icons.check_circle, color: Colors.green) : Icon(Icons.cancel, color: Colors.red),
),

      ],
    ),);
  });
} 

displayRequiredNCS.add(
  Row(
    mainAxisAlignment: MainAxisAlignment.start,
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      Container(
        padding: EdgeInsets all(5),
        width: 200,
        child: Text(
          '    ${r.diagnosis}',
          style: TextStyle(
              fontSize: mediumFontSize,
              color: colorTextDefault,
              fontWeight: FontWeight normal
          ),
        ),
      ),
      Expanded(
        child: Container(
          padding: EdgeInsets all(5),
          child: Column(
            mainAxisAlignment: MainAxisAlignment start,
            crossAxisAlignment: CrossAxisAlignment start,
            children: criteriaRow,
          ),
        ),
      ),
    ],
  ),
);

});

print('final');
return 'test';

}

英文:

Update 3: ok finally figured out that even if I get everything to build into a list of widgets async, when I go to display the widgets it hangs up. You’d think that listview would work since it should only load the items in view, but even that hangs and is slow to scroll.

Update 2: I deleted lines until I found that the single line that causes the delay (i.e. isn't run asyncronously no matter what I try) is this: criteriaRow.add(Row(...)). I've scoured the internet but it doesn't seem that adding things to a list can be done asyncronously. I must be doing something wrong...

I know how to run async functions and I can see how to use a FutureBuilder, but those are for when the data gathering itself is slow. In this case, I can build the lists and data I need very quickly. But, when I go to create the actual final widget, it takes around 4-5 seconds and hangs up the main thread. How can I build a widget asynchronously?

The clear problem is the for loops I have in the widget (see below). When I delete them, it loads quickly.

Column(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Flexible(
            child: SingleChildScrollView(
              child: Card(
                  child: Container(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.start,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        
                        for(var i in displayRequired1) i,
                        for(var i in displayRequired2) i,

                      ],
                    ),
                  )
              ),
            )
        ),

      ],
    );

UPDATE: more complete code (the complete code is way too long to add).

Function that initiates list generation:

Future&lt;String&gt; solveCase() async {

  display = displayType.summary;

  // Parse studies early so data is available
  List&lt;ParseTest&gt; ncsResult = [];
  
  // Build required NCS
  displayRequiredNCS.add(
    Row(
      mainAxisAlignment: MainAxisAlignment.start,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Container(
          padding: EdgeInsets.all(5),
          width: 200,
          child: Text(
            &#39;Nerve Studies&#39;,
            style: TextStyle(
                fontSize: largeFontSize,
                color: colorTextDefault,
                fontWeight: FontWeight.normal
            ),
          ),
        ),
        Expanded(
          child: Container(
            padding: EdgeInsets.all(5),
            child: Text(
              &#39;&#39;,
              style: TextStyle(
                  fontSize: largeFontSize,
                  color: colorTextDefault,
                  fontWeight: FontWeight.normal
              ),
            ),
          ),
        ),
      ],
    ),
  );
  print(&#39;NCS length: ${ncsResult.length}&#39;);
  ncsResult.forEach((r) {
    List&lt;Widget&gt; criteriaRow = [];
    if(r.prettyCriteria[0] == &#39;-&#39; || r.prettyCriteria[0] == &#39;+&#39;){
      r.prettyCriteria.split(&#39;\n&#39;).forEach((e) {
        criteriaRow.add(Row(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Expanded(
              child: Container(
                padding: EdgeInsets.all(5),
                child: Text(
                  &#39;${e.substring(1)}&#39;,
                  style: TextStyle(
                      fontSize: mediumFontSize,
                      color: colorTextDefault,
                      fontWeight: FontWeight.normal
                  ),
                ),
              ),
            ),
            Container(
              padding: EdgeInsets.all(5),
              alignment: Alignment.center,
              width: 200,
              child: e[0] == &#39;+&#39; ? Icon(Icons.check_circle, color: Colors.green) : Icon(Icons.cancel, color: Colors.red),
            ),

          ],
        ),);
      });
    } 

    displayRequiredNCS.add(
      Row(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Container(
            padding: EdgeInsets.all(5),
            width: 200,
            child: Text(
              &#39;    ${r.diagnosis}&#39;,
              style: TextStyle(
                  fontSize: mediumFontSize,
                  color: colorTextDefault,
                  fontWeight: FontWeight.normal
              ),
            ),
          ),
          Expanded(
            child: Container(
              padding: EdgeInsets.all(5),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: criteriaRow,
              ),
            ),
          ),
        ],
      ),
    );

  });

  

  print(&#39;final&#39;);
  return &#39;test&#39;;

}

答案1

得分: 2

你可以合并两个列表displayRequired1displayRequired2,然后使用ListView.builderListView在需要时构建。

final combinedDisplayRequired = [...displayRequired1, ...displayRequired2];
Column(
  mainAxisSize: MainAxisSize.min,
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Flexible(
      child: ListView.builder(
        itemCount: combinedDisplayRequired.length,
        itemBuilder: (context, index) => combinedDisplayRequired[index],
      ),
    ),
  ],
);
英文:

You can combine the both lists displayRequired1 and displayRequired2, then use ListView.builder, ListView builds when required.

  final combinedDisplayRequired = [...displayRequired1, ...displayRequired2];
  Column(
    mainAxisSize: MainAxisSize.min,
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      Flexible(
        child: ListView.builder(
          itemCount: combinedDisplayRequired.length,
          itemBuilder: (context, index) =&gt; combinedDisplayRequired[index],
        ),
      ),
    ],
  );

huangapple
  • 本文由 发表于 2023年2月27日 00:25:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/75573379.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定