【问题标题】:What is the correct way to execute initial network request in Flutter?在 Flutter 中执行初始网络请求的正确方法是什么?
【发布时间】:2021-03-23 09:42:39
【问题描述】:

我有以下代码,用于获取屏幕的初始数据,这个 SchedulerBinding 似乎是一个 hack,但如果我删除它,请求数据就会丢失。

我认为这是因为小部件(streamBuilders 等)尚未构建。

有什么办法可以解决这个问题吗?

全屏代码:https://gist.github.com/Turbozanik/7bdfc69b36fea3dd38b94d8c4fcdcc84

完整的集团代码:https://gist.github.com/Turbozanik/266d3517a297b1d08e7a3d7ff6ff245f

【问题讨论】:

  • 你不能在initState中加载数据
  • 会试试的,给我一分钟
  • 不,数据仍然丢失。可能我可以在 createState 中运行请求,并将初始数据传递给状态,但不确定。

标签: flutter flutter-layout flutter-http


【解决方案1】:

SchedulerBining 不是黑客,根据文档 addPostFrame 调用回调只有一次,如果你删除它,你的流永远不会得到数据 但您可以在 iniState 中调用流加载

void initState(){
 super.initState();
 _mblock.loadSpotMock();

}

【讨论】:

  • 您需要向我们提供有关 loadSpotMock 和所有小部件的更多信息
  • 贴出全屏/块代码,看原问题。
【解决方案2】:

您可以在 initState 方法中异步加载数据,同时您可以显示加载器或消息。加载数据后,调用 setState 重新绘制小部件。

这是一个例子:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatefulWidget {
  @override
  createState() => new MyWidgetState();
}

class MyWidgetState extends State<MyWidget> {
  String _data;
  
  Future<String> loadData() async {
    // Simulate a delay loading the data
    await Future<void>.delayed(const Duration(seconds: 3));

    // Return the data
    return "This is your data!";
  }
  
  @override
  initState() {
    super.initState(); 

    // Call loadData asynchronously   
    loadData().then((s) { 
      // Data has loaded, rebuild the widget
      setState(() { 
        _data = s; 
      });
    });
  }
  
  @override
  Widget build(BuildContext context) {
    if (null == _data) {
      return Text("Loading...");
    }
    
    return Text(_data);
  }
}

您可以在https://dartpad.dartlang.org进行测试

它是这样工作的:

  1. initState 将异步调用 loadData,然后 build 方法将绘制小部件。
  2. 当 loadData 返回时,调用 setState 将重绘小部件。

使用 StreamBuilder

以下示例使用 StreamBuilder 来显示加载后的数据:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatefulWidget {
  @override
  createState() => new MyWidgetState();
}

class MyWidgetState extends State<MyWidget> {
  // Create a stream and execute it
  final Stream<String> _myStream = (() async* {
    // Simulate a delay loading the data
    await Future<void>.delayed(const Duration(seconds: 3));
    
    // Return the data
    yield "This is your data!";
  })();
  
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<String>(
      stream: _myStream,
      builder: (BuildContext context, s) {  
        String result;
        
        if (s.hasError) {
          result = "Error";
        }
        else {
          if (s.connectionState == ConnectionState.done) {
            result = s.data; 
          }
          else {
            result = "Loading...";
          }
        }
        
        return Text(result);
      }
    );
  }
}

希望这会有所帮助:)

【讨论】:

  • 如果我使用状态,它会工作,但我使用流和streamBuilders更新ui,所以当我收到新数据时,它应该更新,但它不是这样工作的。
  • @Void 也许你应该发布你的代码而不是截图。
  • 给我一点时间,我会创建一个要点
  • 更新初始问题,看看
  • @Void 你的集团永远不会产生结果..?我正在更改我的示例代码以使用 StreamBuilder,请给我几分钟。
猜你喜欢
  • 2019-12-20
  • 1970-01-01
  • 1970-01-01
  • 2019-03-12
  • 1970-01-01
  • 2018-03-15
  • 2017-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多