无法从 api 获取数据,Future 总是返回 null - 颤振

Posted

技术标签:

【中文标题】无法从 api 获取数据,Future 总是返回 null - 颤振【英文标题】:Cannot fetch data from api, Future always returns null - flutter 【发布时间】:2021-07-30 21:11:21 【问题描述】:

我正在尝试从 API 中获取数据。只是为了测试我使用的是 API URL:https://jsonplaceholder.typicode.com/todos/1,它具有以下 JSON 对象:


  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false

我在网上按照一个示例进行了几乎完全调整以匹配我想要的工作流程,但下面的 snapshot.hasData 返回 false。

class Home extends StatelessWidget 
  final String accountNum;
  Home(this.accountNum);
  final String apiUrl = "https://jsonplaceholder.typicode.com/todos/";

  Future<Map<String, dynamic>> fetchData() async 
    //accountNum below is passed from a previous screen, in this case I pass '1'
    //I printed it to make sure that '1' is passed and it is correct
    var result = await http.get(apiUrl+accountNum);
    //I printed the below and it also gave me the json from the api
    //print(json.decode(result.body));
    return json.decode(result.body);
  

  String _MeterNum(dynamic account)
    return account['title'];
  

@override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text('Account Data'),
      ),
      body: Container(
        child: FutureBuilder<Map<String, dynamic>>(
          future: fetchData(),
          builder: (BuildContext context, AsyncSnapshot snapshot) 
            if(snapshot.hasData)
              print(_MeterNum(snapshot.data[0]));
              return ListView.builder(
                  padding: EdgeInsets.all(8),
                  itemCount: snapshot.data.length,
                  itemBuilder: (BuildContext context, int index)
                    return
                      Card(
                        child: Column(
                          children: <Widget>[
                            ListTile(
                              leading: CircleAvatar(
                                  radius: 30,
                                  backgroundImage: NetworkImage(snapshot.data[index]['picture']['large'])),
                              //I realize this will just show the same thing 
                              //but I was just keeping the format of the example I was following
                              title: Text(_MeterNum(snapshot.data[index])),
                              subtitle: Text(_MeterNum(snapshot.data[index])),
                              trailing: Text(_MeterNum(snapshot.data[index])),
                            )
                          ],
                        ),
                      );
                  );
            else 
              return Center(child: CircularProgressIndicator());
            
          ,


        ),
      ),
    );
  

返回的是CircularProgressIndicator() 到模拟器屏幕,表明snapshot.hasData 是假的。我没有在控制台或任何东西中收到任何错误,所以我不确定如何继续。

---编辑--- 使用评论者的建议对上面的代码进行了更改:

将返回类型从 Future 更改为 Future> 并更改了 'return json.decode(result.body)['results'];' '返回 json.decode(result.body)'

现在我收到以下错误:

以下 NoSuchMethodError 被抛出构建 FutureBuilder>(脏,状态: _FutureBuilderState>#a10d4):

在 null 上调用了方法“[]”。收件人:空

尝试调用:[] ("title")

【问题讨论】:

你的响应是一个 json 对象,你正在处理 List 这就是问题 添加到上面的评论(将返回类型从 Future> 更改为 Future>):api 响应没有 'results' 属性,所以你应该改变'return json.decode(result.body)['results'];' '返回 json.decode(result.body)'; 现在我得到一个错误。我已在原帖中编辑并添加。 【参考方案1】:

API 响应是一个 JSON 对象


  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false

并且仅包含 userIdidtitlecompleted 成员

请考虑从对象获取而不是引用索引。

替换

snapshot.data[index]

 snapshot.data

还有

snapshot.data['picture']['large']

您的 JSON 对象中没有 picture 数据,请尝试对该代码进行注释或添加图片

【讨论】:

天哪,谢谢。我已经尝试解决这个问题一周了! 你能帮我检查我的最新问题吗?一直没有取得任何进展,也找不到任何其他方式与您联系, 对不起,我设法弄清楚了?感谢您的回复,我开始绝望了【参考方案2】:

改变

title: Text(_MeterNum(snapshot.data[index])),
subtitle: Text(_MeterNum(snapshot.data[index])),
trailing: Text(_MeterNum(snapshot.data[index])),

title: Text(_MeterNum(snapshot.data)),
subtitle: Text(_MeterNum(snapshot.data)),
trailing: Text(_MeterNum(snapshot.data)),

没有像 ['picture']['large'] 这样的键,所以在 ListTile

中注释掉那个键

【讨论】:

【参考方案3】:

在检查 hasData 之前,请执行以下操作:

if (snapshot.connectionState == ConnectionState.done) 
              // your code

编辑

您的要求

var result = await http.get(apiUrl+accountNum);

返回 JSON 对象而不是 JSON 列表。但是您的 fetchData 方法的返回类型在您将其更新为 Future> 之前是 List。 像这样写你的方法

Future<Map<String, dynamic>> fetchData() async 
    var result = await http.get(apiUrl+accountNum);
    return json.decode(result.body);

不需要 json.decode(result.body)['results'],因为您只获取对象而不是列表。

【讨论】:

我做了 if (snapshot.connectionState == ConnectionState.done) print("connected");并得到了“连接”,但我也尝试了上面的两个 cmets 建议,现在我有一个错误!就是这样。 嘿,对,我也改变了它,但我在上面的编辑中产生了 NoSuchMethodError。不知道如何解决这个错误,我推测快照抓取了一个空值,但 api 是一个简单的示例 api,它正在运行并且函数正在连接,所以不确定。

以上是关于无法从 api 获取数据,Future 总是返回 null - 颤振的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中返回 Future<Response>?

Future<int> 无法从 Firebase 获取数据

Future 异步函数的返回值问题

C++11 future.wait_for() 总是返回 future_status::timeout

无法从 Play 2.4 中的 WebSocket 返回 Future[JsValue] 内的 json

REST GET 在 Future Builder 中返回无效参数