如何使用免费和公共的 Rapid API 并在 Flutter 应用程序中调用 API

Posted

技术标签:

【中文标题】如何使用免费和公共的 Rapid API 并在 Flutter 应用程序中调用 API【英文标题】:How to use the free and public Rapid API and call the API in the flutter Application 【发布时间】:2021-11-03 21:40:11 【问题描述】:

例如,我订阅了一个名为“https://rapidapi.com/rapidapi/api/movie-database-imdb-alternative”的免费公共 API

其java代码sn-ps如下

OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
    .url("https://movie-database-imdb-alternative.p.rapidapi.com/?s=Avengers%20Endgame&r=json&page=1")
    .get()
    .addHeader("x-rapidapi-host", "movie-database-imdb-alternative.p.rapidapi.com")
    .addHeader("x-rapidapi-key", "my recieved API Key")
    .build();

Response response = client.newCall(request).execute();

现在我的查询是如何在颤振应用程序中使用并调用?如果我想使用“获取 ID 或标题”来显示电影名称,则需要调用什么 url 和标题的详细信息

我的flutter代码如下

 import 'dart:convert';
import 'package:http/http.dart' as http;


class APIService 
  // API key
  // Base API url
  static const String _baseUrl = "https://movie-database-imdb-alternative.p.rapidapi.com/?s=Avengers%20Endgame&r=json&page=1";
  // Base headers for Response url
  static const Map<String, String> _headers = 
  "x-rapidapi-key": "*****************",
    "x-rapidapi-host": "movie-database-imdb-alternative.p.rapidapi.com",
    
  ;

  // Base API request to get response
  Future<dynamic> get() async 
    Uri uri = Uri.https(_baseUrl,"");
    final response = await http.get(uri, headers: _headers);
    if (response.statusCode == 200) 
      // If server returns an OK response, parse the JSON.
      print("success");
      return json.decode(response.body);
     else 
      print("not success");
      // If that response was not OK, throw an error.
      throw Exception('Failed to load json data');
    
  

我想通过调用 API 在 Flutter 应用程序中显示来自 API 的图像和文本

注意:已经订阅了上面的API,我已经收到了密钥等。

【问题讨论】:

【参考方案1】:

这是完整的示例。您必须捏造它才能放入实际的 JSON 查询结果:

import 'dart:convert';
import 'package:http/http.dart' as http;

import 'package:flutter/material.dart';

void main() 
  runApp(const MyApp());


class MyApp extends StatelessWidget 
  const MyApp(Key? key) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'API Call Demo',
      theme: ThemeData(
        primarySwatch: Colors.orange,
      ),
      initialRoute: '/',
      onGenerateRoute: (settings) => onGenerateRoute(settings),
      onUnknownRoute: pageNotImplementedRoute,
    );
  

  Route? onGenerateRoute(RouteSettings settings) 
    switch (settings.name) 
      case '/':
        return MaterialPageRoute(
          builder: (context) => const MyHomePage(),
        );

      case '/api_page':
        return MaterialPageRoute(
          builder: (context) => const MyAPIPage(),
        );

      default:
        return null;
    
  

  Route pageNotImplementedRoute(RouteSettings settings) 
    return MaterialPageRoute<void>(
      settings: settings,
      builder: (BuildContext context) 
        return Scaffold(
          appBar: AppBar(
            title: const Text('Oops!'),
            leading: IconButton(
              icon: const Icon(Icons.arrow_back),
              onPressed: () 
                Navigator.pop(context);
              ,
            ),
          ),
          body: Center(
            child: Text(
              'Page Not Implemented',
              textAlign: TextAlign.center,
              style: Theme.of(context).textTheme.headline6,
            ),
          ),
        );
      ,
    );
  


class MyHomePage extends StatefulWidget 
  const MyHomePage(Key? key) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();


class _MyHomePageState extends State<MyHomePage> 
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: const Text("Home Page"),
        centerTitle: true,
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () => Navigator.pushNamed(context, '/api_page'),
          child: const Text("Call API"),
        ),
      ),
    );
  


class MyAPIPage extends StatelessWidget 
  const MyAPIPage(Key? key) : super(key: key);

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: const Text("API Page"),
        centerTitle: true,
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () => Navigator.pop(context),
        ),
      ),
      body: _buildBody(),
    );
  

  Widget _buildBody() 
    return FutureBuilder<MyData>(
      future: APIService().get(),
      builder: (context, snapshot) 
        if (snapshot.connectionState != ConnectionState.done) 
          return const Center(child: CircularProgressIndicator());
        
        if (snapshot.hasError) 
          return Center(child: Text(snapshot.error.toString()));
        
        if (!snapshot.hasData) 
          return const Center(child: Text("get() returns null!"));
        
        final data = snapshot.data as MyData; // cast to MyData
        return Container(
          padding: const EdgeInsets.all(10),
          color: Colors.grey,
          child: Column(
            children: [
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  const Text("Field1"),
                  Text(data.field1),
                ],
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  const Text("Field2"),
                  Text(data.field2),
                ],
              ),
            ],
          ),
        );
      ,
    );
  


class APIService 
  static const _authority = "sameer-kumar-aztro-v1.p.rapidapi.com";
  static const _path = "/";
  static const _query = "sign": "aquarius", "day": "today";
  static const Map<String, String> _headers = 
    "x-rapidapi-key": "*****************",
    "x-rapidapi-host": "sameer-kumar-aztro-v1.p.rapidapi.com",
  ;

  // Base API request to get response
  Future<MyData> get() async 
    Uri uri = Uri.https(_authority, _path, _query);
    final response = await http.get(uri, headers: _headers);
    if (response.statusCode == HttpStatus.ok) 
      // If server returns an OK response, parse the JSON.
      final jsonMap = json.decode(response.body);
      return MyData.fromJson(jsonMap);
     else 
      // If that response was not OK, throw an error.
      throw Exception('API call returned: $response.statusCode $response.reasonPhrase');
    
  


class MyData 
  final String field1;
  final String field2;

  const MyData(
    this.field1 = '',
    this.field2 = '',
  );

  factory MyData.fromJson(Map<String, dynamic> json) => _$MyDataFromJson(json);


MyData _$MyDataFromJson(Map<String, dynamic> json) => MyData(
      field1: json['field1'] as String? ?? '',
      field2: json['field2'] as String? ?? '',
    );

【讨论】:

非常感谢您提供完整的解决方案和示例。由于 API 限制和我猜的错误密钥,任何在调用 API 之后的方式都显示为“异常:返回的 API 调用:403 禁止”。你能给我工作 API 和测试密钥吗? 我没有此 API 的密钥,但您可以试试 News API。您可以免费注册成为开发人员并获取密钥。 newsapi.org 非常感谢您的建议。我会试试的 我已经注册并收到了我通过以下方式使用的新闻 API class APIService static const _authority = "geektime.com/israeli-autotech-companies";静态常量 _path = "/"; static const _query = "sign": "aquarius", "day": "today"; static const Map _headers = "x-newsapi-key": "my key received", "x-omdbapi-host": "geektime.com/israeli-autotech-companies", 但是当我调用这个 API 时,我看到 FormatException :无效的 radix-10 错误显示为“ FormatException:Invalid radix-10 number(at character 1) //www.geektime.com/israeli-autotech-companies/【参考方案2】:

创建一个数据类,其中包含与返回的 JSON 对象对应的字段。在不知道 JSON 字符串是什么的情况下,我无法向您展示该类的外观。

查看json_serializable 包以帮助您创建类(例如MyData)并创建方法MyData.fromJson

然后这样做:

final jsonMap = json.decode(response.body);
return MyData.fromJson(jsonMap);

返回的MyData 对象将包含转换为 Dart 对象的 JSON 对象供您使用。

如下声明get()

Future<MyData> get() async 
  ...
  final jsonMap = json.decode(response.body);
  return MyData.fromJson(jsonMap);
  ...

在您的页面小部件内build() 方法:

return FutureBuilder<MyData>(
  future: get(),
  builder: (context, snapshot) 
    if (snapshot.connectionState != ConnectionState.done) 
      return const Center(child: CircularProgressIndicator());
    
    if (snapshot.hasError) 
      return Center(child: Text(snapshot.error));
    
    if (!snapshot.hasData) 
      return Center(child: Text("get()returns null!"));
    
    final data = snapshot.data as MyData; // cast to MyData
    return Container(...); // use data in here
  

【讨论】:

请指导我如何从 main.dart 页面重定向到 APIPage。我的意思是我的 main.dart 代码将如何导航到 APIPage。我为 ex cricket-live-data.p.rapidapi.com/series 使用快速 API 您必须学习如何使用导航器切换到另一个页面。在 *** 上搜索示例, 我的意思是 api.dart 页面应该是怎样的,应该有 main () 函数等或没有,以及如何从 main.dart 页面返回或导航 您必须将lib 目录下的源代码树分成几个子目录。就我而言,只有main.dartlib 中。我还有pages 目录用于我的所有页面(屏幕)小部件,services 目录用于所有 API 调用类和方法,models 目录用于数据类(映射到 API 调用返回的 JSON 字符串),@ 987654337@ 用于自定义小部件(不是页面)。 main 指定一个主页,从主页您使用导航器push* 方法导航到其他页面。在每个页面的build 方法中调用FutureBuilder 内的API。

以上是关于如何使用免费和公共的 Rapid API 并在 Flutter 应用程序中调用 API的主要内容,如果未能解决你的问题,请参考以下文章

我可以使用哪些免费和公共图像 JSON API 来测试 JSON 请求 [关闭]

C++ 类 - 使用公共变量并在类外定义成员函数

如何通过 Amazon API Gateway (JAVA) 检索用户的公共 IP 地址

服务如何生成和使用公共和秘密 API 密钥?

如何实现一个公共组件库上传到npm并在项目中使用

JMeter - 如何测试REST API / 微服务