【问题标题】:Fetch Api Data Automatically with Interval in Flutter在 Flutter 中以间隔自动获取 API 数据
【发布时间】:2020-04-03 11:39:30
【问题描述】:

在我的颤振应用程序中,我试图显示更新数据。我成功地手动从天气 api 获取数据。但我需要每 5 秒不断地抓取数据。所以它应该自动更新。这是我在 Flutter 中的代码:

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Sakarya Hava',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Sakarya Hava'),
        ),
        body: Center(
          child: FutureBuilder<SakaryaAir>(
            future: getSakaryaAir(), //sets the getSakaryaAir method as the expected Future
            builder: (context, snapshot) {
              if (snapshot.hasData) { //checks if the response returns valid data
                return Center(
                  child: Column(
                    children: <Widget>[
                      Text("${snapshot.data.temp}"), //displays the temperature
                      SizedBox(
                        height: 10.0,
                      ),
                      Text(" - ${snapshot.data.humidity}"), //displays the humidity
                    ],
                  ),
                );
              } else if (snapshot.hasError) { //checks if the response throws an error
                return Text("${snapshot.error}");
              }
              return CircularProgressIndicator();
            },
          ),
        ),
      ),
    );
  }


  Future<SakaryaAir> getSakaryaAir() async {
    String url = 'http://api.openweathermap.org/data/2.5/weather?id=740352&APPID=6ccf09034c9f8b587c47133a646f0e8a';
    final response =
    await http.get(url, headers: {"Accept": "application/json"});


    if (response.statusCode == 200) {
      return SakaryaAir.fromJson(json.decode(response.body));
    } else {
      throw Exception('Failed to load post');
    }
  }
}

我发现这样一个 sn-p 受益于:

// runs every 5 second
Timer.periodic(new Duration(seconds: 5), (timer) {
   debugPrint(timer.tick);
});

可能我需要用这个 sn-p 包装和调用 FutureBuilder,但我不明白该怎么做。

【问题讨论】:

  • 你是否在 initstate 中调用了这个方法?
  • MyApp 是无状态的。如果我让它有状态,那么值得尝试

标签: json api flutter time dart


【解决方案1】:

期货可以有两种状态:已完成或未完成。 Futures 不能“进步”,但 Streams 可以,因此对于您的用例,Streams 更有意义。

你可以这样使用它们:

Stream.periodic(Duration(seconds: 5)).asyncMap((i) => getSakaryaAir())

periodic 每 5 秒发出一次空事件,我们使用 asyncMap 将该事件映射到另一个流中,从而为我们获取数据。

这是工作示例:

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

class ExamplePage extends StatelessWidget {
  Future<String> getSakaryaAir() async {
    String url =
        'https://www.random.org/integers/?num=1&min=1&max=6&col=1&base=10&format=plain&rnd=new';
    final response =
        await http.get(url, headers: {"Accept": "application/json"});

    return response.body;
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: Stream.periodic(Duration(seconds: 5))
          .asyncMap((i) => getSakaryaAir()), // i is null here (check periodic docs)
      builder: (context, snapshot) => Text(snapshot.data.toString()), // builder should also handle the case when data is not fetched yet
    );
  }
}

【讨论】:

  • 嘿@pr0gramist,我知道这有点老了,但我发现你的答案在这里很有用,还有一个问题。您知道如何将其融入使用 bloc 进行状态管理吗?我有几个例子,有你经验的人可能会提供建议。
  • @pianoman102 我认为该集团的 Timer 示例在某种程度上具有可比性:bloclibrary.dev/#/fluttertimertutorial 一旦您设置了股票代码,您就可以发送事件并获取新数据。
  • 是的,我确实看到了,但认为这有点矫枉过正......我在想你可以设置你的 bloc 通过存储库获取事件,然后在某个地方的 ui 中,设置一个计时器每隔一段时间向该集团发送一个 fetchData 事件。但我不知道这是否是最好的方法。
【解决方案2】:

您可以重构您的FutureBuilder 以使用Future 变量,而不是调用FutureBuilder 中的方法。这需要您使用StatefulWidget,您可以在initState 中设置未来,并通过调用setState 对其进行更新。

所以你有一个未来的变量字段,比如:

Future< SakaryaAir> _future;

所以你的initState 看起来像这样:

@override
  void initState() {
    super.initState();
    setUpTimedFetch();
  }

setUpTimedFetch 定义为

  setUpTimedFetch() {
    Timer.periodic(Duration(milliseconds: 5000), (timer) {
      setState(() {
        _future = getSakaryaAir();
      });
    });
  }

最后,您的FutureBuilder 将更改为:

FutureBuilder<SakaryaAir>(
          future: _future,
          builder: (context, snapshot) {
            //Rest of your code
          }),

这是一个 DartPad 演示:https://dartpad.dev/2f937d27a9fffd8f59ccf08221b82be3

【讨论】:

    猜你喜欢
    • 2021-01-02
    • 2021-02-03
    • 2020-08-17
    • 2021-07-20
    • 2021-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-30
    相关资源
    最近更新 更多