首页 > 解决方案 > Flutter,如何通过有限的 api 请求捕获快速变化的 API 数据

问题描述

我有 Riot Games Development API,它有“每 1 秒 20 个请求和每 2 分钟 100 个请求”。我正在尝试制作一个应用程序,通过在游戏开始前每 2 或 3 秒检查一次当前游戏数据的“gameStartTime”值,在游戏开始时通知我。(它返回值 0,直到游戏开始并返回游戏开始时的纪元时间。)问题是这个“gameStartTime”值确实会更改为游戏开始时的纪元时间,但几秒钟后又回到 0。所以当我测试我的应用程序时,它有时不会通知我什么时候应该通知我。我觉得我应该更频繁地发出请求以在它变为 0 之前捕获该值,但我担心 api 限制。我很想就这个问题得到建议。

这些是我用来从 Riot Games API 获取数据的代码:

class MakeRequestScreen extends StatefulWidget {
  final String? derivedId;
  MakeRequestScreen({this.derivedId});
  // Declare a field that holds the Todo.

  @override
  _MakeRequestScreenState createState() => _MakeRequestScreenState();
}

class _MakeRequestScreenState extends State<MakeRequestScreen> {
  late Stream<InGameData> myStream;
  InGameDataDecoder myData = InGameDataDecoder();

  @override
  void initState() {
    super.initState();
    myStream = myData.getData(id: widget.derivedId, url: inGameDataUrl);
    setUpTimedFetch();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('해피로딩'),
      ),
      body: Container(
        child: SafeArea(
          child: Column(
            children: [
              StreamBuilder<InGameData>(
                  stream: myStream,
                  builder: (context, snapshot) {
                    if (snapshot.data == null) {
                      return Text(
                        'Looking for your match,,,',
                        style: TextStyle(fontSize: 30.0),
                      );
                    } else {
                      switch (snapshot.connectionState) {
                        case ConnectionState.none:
                          return Text('Select a lot');
                        case ConnectionState.waiting:
                          return Expanded(
                              child:
                                  Center(child: CircularProgressIndicator()));
                        case ConnectionState.active:
                          if (snapshot.data!.gameStartTime.toString().length >
                                  3 &&
                              snapshot.data!.gameStartTime.toString().length !=
                                  0) {
                            return Expanded(
                                child: Center(
                                    child: Text(
                              'Your game has started.',
                              style: TextStyle(
                                fontSize: 30.0,
                                color: Colors.greenAccent,
                              ),
                            )));
                          }
                          if (snapshot.data!.gameStartTime.toString() == '0') {
                            return Text(
                              'Got into loading screen!',
                              style: TextStyle(
                                fontSize: 30.0,
                                color: Colors.yellow,
                              ),
                            );
                          }
                          return Text('hmm,,,');
                        case ConnectionState.done:
                          return Text('done');
                      }
                    }
                  })
            ],
          ),
        ),
      ),
    );
  }

  setUpTimedFetch() {
    Timer.periodic(Duration(seconds: 2), (timer) {
      setState(() {
        // maybe i need to make this function repeated
        myStream = myData.getData(id: widget.derivedId, url: inGameDataUrl);
      });
    });
  }
}

正在使用的类:

class InGameData {
  final int? gameStartTime;

  InGameData({required this.gameStartTime});

  factory InGameData.fromJson(Map<String, dynamic> json) {
    return InGameData(gameStartTime: json['gameStartTime']);
  }
}

class InGameDataDecoder {
  Stream<InGameData> getData(
      {required String? id, required String url}) async* {
    http.Response response =
        await http.get(Uri.parse('$url$id?api_key=$apiKey'));

    if (response.statusCode == 200) {
      yield* Stream.periodic(Duration(seconds: 2), (int abc) {
        return InGameData.fromJson(json.decode(response.body));
      });
    } else {
      throw Exception('exception');
    }
  }
}

标签: flutterapi

解决方案


在这种情况下,您通常会使用Webhook基本上是反向 API 的 a。您将提供一个 URL,Riot Games 服务器调用该 URL 以在游戏开始时通知您。如果 Riot 不提供该功能,那么您无能为力。

您的问题是此类 API 的常见限制。

编辑:简要看一下 Riot API,我找不到这样的功能。


推荐阅读