0

我在尝试使用 Flutter 的 FutureBuilder 从远程 URL 迭代对象的 JSON 数组时遇到问题。

我的目标是:

  • 从 API 获取 JSON 数据
  • 将数据输出到 2 列 gridview 布局

JSON 数据是一个对象数组(或 dart 中的 Maps 列表),对象具有简单的字符串数据。

我知道我需要构建一个未来来从 API 获取数据并解码 JSON,然后我需要创建一个 FutureBuilder 来将列表数据输出到我的 Gridview Builder 中。这就是我在下面的代码中尝试做的事情。

import 'dart:convert';
import 'dart:async';
import 'dart:core';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;


class HomeSection extends StatefulWidget {
  @override
  _HomeSectionState createState() => _HomeSectionState();
}

class _HomeSectionState extends State<HomeSection> {
  @override
  void initState() {
    super.initState();
  }

  Future<List<dynamic>> fetchSectionData() async {
    String dataUrl =
        'https://www.thisisthejsonapilink.co.uk/fetch-data';
    var response = await http.get(Uri.parse(dataUrl));
    if (response.statusCode == 200) {
      return jsonDecode(response.body);
    } else {
      throw Exception('Failed to get the data');
    }
  }

  @override
  Widget build(BuildContext context) {

    return FutureBuilder(
      future: fetchSectionData,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          return GridView.builder(
            itemCount: 12,
            gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
              maxCrossAxisExtent: 300,
              crossAxisSpacing: 16.0,
              mainAxisSpacing: 18.0,
              childAspectRatio: MediaQuery.of(context).size.height / 930,
            ),
            itemBuilder: (BuildContext context, int index) => GestureDetector(
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => OtherScreen()),
                );
              },
              child: Column(
                children: [
                  Container(
                    margin: const EdgeInsets.only(bottom: 12.0),
                    height: 144,
                  ),
                  Text(
                    snapshot.data[index].title,
                  ),
                  Text(
                    snapshot.data[index].duration + ' - ' + snapshot.data[index].type,
                  ),
                ],
              ),
            ),
          );
        } else {
          return Center(
            child: CircularProgressIndicator(
              color: Colors.black,
            ),
          );
        }
      },
    );
  }
}

我从 API 链接返回的 JSON 结构如下:

[
  {
    "Title": "Audio 1",
    "Duration": "5 min",
    "type": "audio",
    "bodyText": "lorem ipsum blah blah audio",
    "url": "https://www.silvermansound.com/music/dirty-gertie.mp3"
  },
  {
    "Title": "Video 1",
    "Duration": "5 min",
    "type": "video",
    "bodyText": "lorem ipsum blah blah video",
    "url": "https://assets.mixkit.co/videos/preview/mixkit-woman-wearing-a-mask-while-running-40158-large.mp4"
  },
  {
    "Title": "Audio 2",
    "Duration": "5 min",
    "type": "audio",
    "bodyText": "lorem ipsum blah blah audio",
    "url": "https://www.silvermansound.com/music/dirty-gertie.mp3"
  },
  {
    "Title": "Video 2",
    "Duration": "5 min",
    "type": "video",
    "bodyText": "lorem ipsum blah blah video",
    "url": "https://assets.mixkit.co/videos/preview/mixkit-woman-wearing-a-mask-while-running-40158-large.mp4"
  },
  {
    "Title": "Audio 3",
    "Duration": "5 min",
    "type": "audio",
    "bodyText": "lorem ipsum blah blah audio",
    "url": "https://www.silvermansound.com/music/dirty-gertie.mp3"
  },
  {
    "Title": "Video 3",
    "Duration": "5 min",
    "type": "video",
    "bodyText": "lorem ipsum blah blah video",
    "url": "https://assets.mixkit.co/videos/preview/mixkit-woman-wearing-a-mask-while-running-40158-large.mp4"
  },
]

这是我在 VS 代码调试控制台中遇到的错误:

The argument type 'Future<List<dynamic>> Function()' can't be assigned to the parameter type 'Future<Object?>?'.

红线出现在我尝试在 FutureBuilder 中定义我的未来的地方fetchSectionData

return FutureBuilder(
      future: fetchSectionData,
      builder: (context, snapshot) {

我不确定这个错误是什么意思。有人可以解释一下吗?Future 肯定会返回一个 <List>,但是如何将这个列表放入 futurebuilder 中,以便我可以迭代它并将数据输出到 gridview 中?

我对 Flutter 相当陌生,并且来自 javascript Web 背景,通常在 javascript 中,您可以循环遍历数组并以这种方式输出。我很想在这里这样做,但我知道那是不对的。

当我查看有关如何从 Internet 获取数据的 Flutter 文档时,它提到我必须将响应转换为自定义 dart 对象,但我尝试的任何方法似乎都不起作用。

感谢你的帮助!

4

2 回答 2

1

尝试这个 !

return FutureBuilder<List<dynamic>>(
      future: fetchSectionData,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          return GridView.builder(
            itemCount: 12,
            gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
              maxCrossAxisExtent: 300,
              crossAxisSpacing: 16.0,
              mainAxisSpacing: 18.0,
              childAspectRatio: MediaQuery.of(context).size.height / 930,
            ),
            itemBuilder: (BuildContext context, int index) => GestureDetector(
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => OtherScreen()),
                );
              },
              child: Column(
                children: [
                  Container(
                    margin: const EdgeInsets.only(bottom: 12.0),
                    height: 144,
                  ),
                  Text(
                    '${snapshot.data[index]['Title']}',
                  ),
                  Text(
                    '${snapshot.data[index]['Duration'] + ' - ' + snapshot.data[index]['type']}',
                  ),
                ],
              ),
            ),
          );
        } else {
          return Center(
            child: CircularProgressIndicator(
              color: Colors.black,
            ),
          );
        }
      },
    );
于 2021-06-15T05:30:12.750 回答
0

你必须像这样传递函数

      future: fetchSectionData(),
  • 在你的 GridView 中最好使用
...
itemCount: snapshot.data.length
...
  • List<dynamic> 等于 List it self
Future<List> fetchSectionData() async{
...
  • 确定 FutureBuilder 的类型是一个好习惯
FutureBuilder<List>(
...
于 2021-06-14T20:51:49.930 回答