如何在 Flutter 中的 onPresseed 按钮后获得 JSON 响应 // Dart

How to get JSON response after onPresseed button in Flutter // Dart

我在获取 JSON 数据时没有遇到任何问题按下按钮获取 JSON response.body 打印成功但 JSON 响应在我给 _addressController 值执行 if 条件之前执行,因此异常显示在打印状态上。所以请查看我的代码并帮助我解决问题

import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:core';
import 'dart:convert';
import 'package:http/http.dart'as http;
import 'string.dart';



void main() => runApp(MyApp());

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Retrieve Text Input',
      home: MyCustomForm(),
    );
  }
}

class MyCustomForm extends StatefulWidget {
  const MyCustomForm({Key? key}) : super(key: key);

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

 class _MyAppState extends State<MyCustomForm> {

   final _formKey = GlobalKey<FormState>();

   var url1 = 'This is my first off url';
  
   var _addressControler = TextEditingController();
   late Future<Balance> futureBalance;



   @override
   void initState() {
     super.initState();
     futureBalance = fetchBalance();
   }

   Future<Balance> fetchBalance() async {
    
     http.Response response =
     await http.get(Uri.parse(url1+_addressControler.text));

     print(response.body);

     if (response.statusCode == 200) {
       return Balance.fromJson(jsonDecode(response.body));
     } else {
       throw Exception('Failed to load album');
    }
   }

   @override
   Widget build(BuildContext context) {
     return MaterialApp(
         title: 'Fetch Data Example',
         theme: ThemeData(
           primarySwatch: Colors.blue,
         ),
         home: Scaffold(
           
           appBar: AppBar(
             title: Text('Fetch Data Example'),
           ),
           body: Center(
             key: _formKey,
             child: Column(
                 children: [
                   Padding(
                     padding: const EdgeInsets.all(10.0),
                     child: TextField(
                       controller: _addressControler,
                       decoration: InputDecoration(
                         labelText: 'Enter the address...',
                         labelStyle: TextStyle(color: Colors.blue),
                         border: new OutlineInputBorder(
                             borderSide: new BorderSide(color: Colors.black)),),
                     ),
                   ),
                   Padding(
                     padding: const EdgeInsets.symmetric(vertical: 16.0),
                     child: ElevatedButton(
                       onPressed: () async {
                         await fetchBalance();
                       },
                       child: const Text('Submit'),
                     ),
                   ),
                   Padding(
                     padding: const EdgeInsets.symmetric(vertical: 16.0),
                     child: Text("${_addressControler.text}"),

                   ),
                   Container(
                     //color: Colors.blueAccent,
                     child: FutureBuilder<Balance>(
                       future: futureBalance,
                       builder: (context, index) {
                         if (index.hasData) {
                           print(index.data!.height);
                           var x = (index.data!.result[0].amount);
                           var y = int.parse(x);
                           assert(y is int);
                           var z = (y / 1000000);
                           print(z); 
                           return Row(
                               mainAxisAlignment: MainAxisAlignment.center,
                               children: [
                                 Text('${z.toString()}',
                                   style: TextStyle(fontSize: 20,),),
                               ]);
                         } else if (index.hasError) {
                           return Text("${index.error}");
                         }
                       
                         return CircularProgressIndicator();
                       },
                     ),
                   ),
                 ]
             ),
           ),
         )
     );
   }
 }

我对 fetchBalance() 函数有疑问。 if 条件在我单击 onPressed 按钮之前执行,但是 我在给定 TextField 并提交 onPressed 后执行条件。那么,有没有什么办法可以解决这个问题,请帮助我...

我不确定我是否理解您的问题,但您似乎遇到了错误,因为 fetchBalance 在您预期之前执行了。

好吧,您在 initState() 方法中调用了 futureBalance = fetchBalance();,因此代码会在您的小部件初始化时执行,而不仅仅是在您按下按钮后执行。这意味着,您尝试在不附加 _addressControler.text.

的情况下解析 url

另外,你也可以这样使用

 fetchBalance().then((balance) {
      setState(() {
        _balance = balance; //need to create one variable of type Balance
      });
    });

最好将 setState() 放在异步调用中:

 Future<Balance> fetchBalance() async {
    
     http.Response response =
     await http.get(Uri.parse(url1+_addressControler.text));

     print(response.body);

     if (response.statusCode == 200) {
         setState(() {
             _balance = Balance.fromJson(jsonDecode(response.body));
         });
     } else {
       throw Exception('Failed to load album');
    }
   }

首先,我删除了 initState(),然后我使用 setState() 作为 onPressed() 来调用 API 函数 fetchBalance() 在它运行良好的状态下..

child: ElevatedButton(
                    onPressed: ()  {
                      setState(() {
                        fetchBalance();
                      });
                      fetchBalance();
                    },
                    child: const Text('Submit'),
                  ),
                ),