Flutter 有执行顺序吗?

Is there an execution order sequence in Flutter?

我有问题,我想保存我网站的数据。仅当传输 phone 号码时才应传输此数据。但是我编写的程序并没有从下到上执行,我收到错误消息“抛出了另一个异常:NoSuchMethodError:方法'[]'被调用为空。” 在调试器中,我看到在“if (!await MobileNumber.hasPhonePermission)”之后它直接进入小部件构建,在那里它试图显示尚未准备好的 _loadHtml。有没有办法改变Flutter中期货的顺序或者有更好的解决方案来解决这个问题?

Future<void> getDataFromServer() async {
    final responsew = await initMobilNumberState();
    final response = await _fetchSampleData();

    if (response.statusCode == 200) {
      Map<String, dynamic> data = json.decode(response.body);
      _list = data.values.toList();
    } else {
      // If the server did not return a 200 OK response,
      // then throw an exception.
      showAlertNoInternet(context);
      print('Failed to load data from server');
    }
  }

  Future<http.Response> _fetchSampleData() async {
    String s = _mobileNumber;
    print(s);
    return http.get('http://test-site' + _mobileNumber);
  }

  Future<void> initMobilNumberState() async {
    if (!await MobileNumber.hasPhonePermission) {
      await MobileNumber.requestPhonePermission;
      return;
    }
    String mobileNumber = '';

    try {
      mobileNumber = await MobileNumber.mobileNumber;
      _simCard = await MobileNumber.getSimCards;
    } on PlatformException catch (e) {
      debugPrint("Failed to get mobile number because of '${e.message}'");
    }

    if (!mounted) return;
    setState(() {
      var re = RegExp(r'\+[^]*');
      _mobileNumber = mobileNumber.replaceRange(0, 3, ''.replaceAll(re, '+'));
    });
  }


  Widget build(BuildContext context) {
    String _loadHtml(String) {
      return r'''
''' +
          _list[1][0] +
          '''
</body>
</html>
''';
    }

    String _loadHtml2(String) {
      var foo = '';
      for (int i = 0; i < _list[0].length; i++) {
        foo += r'''
          ''' +
            _list[0][i] +
            '''
          </body>
          </html>
          ''';
      }

      return foo;
    }

    return Scaffold(
      appBar: AppBar(
        backgroundColor: Color.fromRGBO(35, 31, 32, 1),
        actions: <Widget>[
          NavigationControls(_controller.future),
        ],
      ),
      body: Builder(builder: (BuildContext context) {

        return WebView(
          initialUrl:

              new Uri.dataFromString(_loadHtml(String), mimeType: 'text/html')
                      .toString() +
                  _loadHtml2(String),

          ///
          javascriptMode: JavascriptMode.unrestricted,
          onWebViewCreated: (WebViewController webViewController) {
            _controller.complete(webViewController);
          },
          javascriptChannels: <JavascriptChannel>[
            _toasterJavascriptChannel(context),
          ].toSet(),

          navigationDelegate: (NavigationRequest request) {
            for (int i = 0; i < _list[2].length; i++) {
              if (request.url.startsWith(_list[2][i])) {
                print('allowing navigation to $request}');
                return NavigationDecision.navigate; //prevent

              }
            }
            return NavigationDecision.prevent;
          },
          onPageStarted: (String url) {
            print('Page started loading: $url');
          },
          onPageFinished: (String url) {
            print('Page finished loading: $url');
          },
          gestureNavigationEnabled: true,
        );
      }),
    );
  }

更新:

  @override
  Widget build(BuildContext context) {
    String _loadHtml(String) {
      return r'''
''' +
          _list[1][0] +
          '''
</body>
</html>
''';
    }

    String _loadHtml2(String) {
      var foo = '';
      for (int i = 0; i < _list[0].length; i++) {
        foo += r'''
          ''' +
            _list[0][i] +
            '''
          </body>
          </html>
          ''';
      }

      return foo;
    }

    FutureBuilder<String>(
      future: getDataFromServer(),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return WebView(
            initialUrl:

                /// Hier werden die HTML Strings eingelesen und als Website angezeigt.
                new Uri.dataFromString(_loadHtml(String), mimeType: 'text/html')
                        .toString() +
                    _loadHtml2(String),

            ///
            javascriptMode: JavascriptMode.unrestricted,
            onWebViewCreated: (WebViewController webViewController) {
              _controller.complete(webViewController);
            },
            javascriptChannels: <JavascriptChannel>[
              _toasterJavascriptChannel(context),
            ].toSet(),

            /// In der [navigationDelegate] wird die WhiteList durch einen for loop durchgeangen.
            navigationDelegate: (NavigationRequest request) {
              for (int i = 0; i < _list[2].length; i++) {
                if (request.url.startsWith(_list[2][i])) {
                  print('allowing navigation to $request}');
                  return NavigationDecision.navigate; //prevent

                }
              }
              return NavigationDecision.prevent;
            },
            onPageStarted: (String url) {
              print('Page started loading: $url');
            },
            onPageFinished: (String url) {
              print('Page finished loading: $url');
            },
            gestureNavigationEnabled: true,
          );
        }
        return CircularProgressIndicator();
      },
    );
  }

问题是在声明中:

if (!await MobileNumber.hasPhonePermission)

这个语句是一个异步语句,即当它完成时,控制继续到下一个语句,并且 if 条件求助于 false,因为 await 语句暂时返回 null。 更好的解决方案是为此类异步语句使用未来构建器,并在等待异步任务完成时显示进度指示器。