Flutter - 多次调用 API 并使用从互联网返回的更改更新 UI

Posted

技术标签:

【中文标题】Flutter - 多次调用 API 并使用从互联网返回的更改更新 UI【英文标题】:Flutter - Making several calls to an API and updating the UI with the changes gotten back from internet 【发布时间】:2021-04-04 09:54:23 【问题描述】:

`

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

class BinDetails 
  BinDetails(this.url);
  String url;
  Future getCardMetadata() async 
    try 
      http.Response response = await http.get(url);
      if (response.statusCode == 200) 
        String data = response.body;
        print(jsonDecode(data));
        return jsonDecode(data);
       else 
        print(response.statusCode);
        print(response.body);
      
     catch (e) 
      print("An error occurred: $e");
    
  

  
`

`
import 'package:flutter/material.dart';
    import 'package:extension/extension.dart';
    import 'package:mask_text_input_formatter/mask_text_input_formatter.dart';
    import 'package:binlist/services/networking.dart';
    
    String url = "https://lookup.binlist.net/$cardNumber";
    String cardNumber = "";
    String cardScheme = "-";
    String cardType = "-";
    String cardLength = "-";
    String prepaid = "-";
    String bankName = "-";
    String countryName = "-";
    
    class CardDetails extends StatefulWidget 
      @override
      _CardDetailsState createState() => _CardDetailsState();
    
    
    class _CardDetailsState extends State<CardDetails> 
      Future<dynamic> getCalledCardMetaData() async 
        BinDetails getBinDetails = BinDetails(url: url);
        var cardMetaData = await getBinDetails.getCardMetadata();
    
        if (cardMetaData['scheme'] == null) 
          setState(() 
            cardScheme = "-";
          );
        
        if (cardMetaData['type'] == null) 
          setState(() 
            cardType = "-";
          );
        
    
        if (cardMetaData['number']['length'] == null) 
          setState(() 
            cardLength = "-";
          );
        
        if (cardMetaData['prepaid'] == null) 
          setState(() 
            prepaid = "-";
          );
        
        if (cardMetaData['bank'] == null) 
          setState(() 
            bankName = "-";
          );
        
        if (cardMetaData['country'] == null) 
          setState(() 
            countryName = "-";
          );
        
        setState(() 
          cardScheme = cardMetaData['scheme'];
          cardType = cardMetaData['type'];
          cardLength = cardMetaData['number']['length'].toString();
          if (cardLength == "null") 
            cardLength = "-";
          
          prepaid = cardMetaData['prepaid'].toString();
          if (prepaid == "false") 
            prepaid = "No";
           else if (prepaid == "true") 
            prepaid = "Yes";
           else if (prepaid == "null") 
            prepaid = "-";
          
          bankName = cardMetaData['bank']['name'];
          countryName = cardMetaData['country']['name'];
          print(cardScheme);
          print(countryName);
          print(cardLength);
          print(cardType);
          print(bankName);
          print(prepaid);
        );
        return cardMetaData;
      
    
      final _imputedNumber = TextEditingController();
    
      void clearCardNumber() 
        setState(() 
          _imputedNumber.clear();
          cardScheme = "-";
          cardType = "-";
          cardLength = "-";
          prepaid = "-";
          bankName = "-";
          countryName = "-";
          print(cardNumber);
        );
      
    
      @override
      Widget build(BuildContext context) 
        var maskFormatter = MaskTextInputFormatter(
            mask: '#### ####', filter: "#": RegExp(r'[0-9]'));
        return Scaffold(
          appBar: AppBar(
            title: Text(
              'Bin List',
            ),
          ),
          body: Column(
            children: [
              Expanded(
                child: Column(
                  children: [
                    Container(
                      width: MediaQuery.of(context).size.width * 0.9,
                      child: TextField(
                        inputFormatters: [maskFormatter],
                        controller: _imputedNumber,
                        onChanged: (value) 
                          String maskedNumber = value;
                          cardNumber =
                              maskedNumber.replaceAll(new RegExp(r'\s'), '');
                          print(cardNumber);
                          print(cardNumber.length);
                         
                          if (cardNumber.length == 8) 
                            getCalledCardMetaData();
                          
                        ,
                        keyboardType: TextInputType.number,
                        textAlign: TextAlign.center,
                        decoration: InputDecoration(
                          contentPadding: EdgeInsets.symmetric(horizontal: 5.0),
                          enabledBorder: UnderlineInputBorder(
                            borderSide: BorderSide(color: Colors.black54),
                          ),
                          focusedBorder: UnderlineInputBorder(
                            borderSide:
                                BorderSide(color: Colors.lightBlue, width: 2.0),
                          ),
                          suffix: TextButton(
                            onPressed: clearCardNumber,
                            child: Icon(
                              Icons.clear,
                              color: Colors.grey.shade600,
                            ),
                          ),
                        ),
                      ),
                    ),`

我制作了一个应用程序,它使用 bin 列表 API (https://lookup.binlist.net/YOUR_CARD_NUMBER_HERE) 来获取卡片的元数据。当我从冷启动应用程序时,输入 CARD A 的卡号,并发出获取请求,我会取回卡元数据并用于更新 UI。当我清除 CARD A 的数字并为 CARD B 输入卡号时,我仍然得到 CARD A 而不是 CARD B 的元数据。但是当我再次从冷启动应用程序并输入 CARD B 的卡号时只有这样,我才能在 UI 上获得 CARD B 的正确元数据。

我试图通过在 TextField 的值发生变化时将卡号打印到控制台来进行调试。我输入了正确的数字,这个输入的数字是发送到 API 的,但是第二张卡的元数据没有从 API 中检索到。我每次都必须从冷启动应用程序以检索正确的元数据。我能做些什么来解决这个问题?谢谢。

[

【问题讨论】:

【参考方案1】:

在评估所有条件后,在您的代码中,尝试在调用 getCalledCardMetaData() 之前调用清除先前值的函数。

if (cardNumber.length == 8) 
    clearCardNumber();
    getCalledCardMetaData();

【讨论】:

这并不能解决问题。它在调用 API 之前清除卡号,当我点击它时,取消图标也会这样做

以上是关于Flutter - 多次调用 API 并使用从互联网返回的更改更新 UI的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 如何将地图从互联网 API 转换为列表?

Flutter:如何在加载页面之前从 Api 获取数据 [关闭]

如何执行带有承诺的函数并通过 API 调用多次检查其值并使用该值执行另一个函数?

Flutter bloc 模式多次重复调用函数

多次 onReceive 使用会导致重复的 API 调用

如何测试从 Flutter 应用程序到 localhost 服务的 api 调用?