【问题标题】:Flutter FutureBuilder snapshot returns Instance of 'Object' instead of dataFlutter FutureBuilder 快照返回“对象”的实例而不是数据
【发布时间】:2021-11-23 15:26:28
【问题描述】:

我是 Flutter 的新手并尝试显示来自 http 帖子的数据

引用自 [1]https://flutter.dev/docs/cookbook/networking/background-parsing 和 [2]https://flutter.dev/docs/cookbook/networking/fetch-data

我尝试在 futurebuilder 上显示数据,但它一直在 Text('${snapshot.data}') 中显示此数据

[Instance of 'DashBoardBanner', Instance of 'DashBoardBanner', Instance of 'DashBoardBanner']

建造者

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  _MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
  late Future<List<DashBoardBanner>> futureBanner;
  @override
  void initState() {
    super.initState();
    futureBanner = getBannerDataFromServer();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
          child: ListView(
            children: [
              Card(
                child: FutureBuilder(
                  future: getBannerDataFromServer(),
                  builder: (context,snapshot){
                    if(snapshot.connectionState == ConnectionState.done){
                      if (snapshot.hasData) {
                        return Text('${snapshot.data}');
                      } else if (snapshot.hasError) {
                        return Text('${snapshot.error}');
                      }
                    }
                    return const CircularProgressIndicator();
                  },
                ),
              )
            ],
          )),
    );
  }
}

类和后请求

class DashBoardBanner {
  final String MsgId;
  final String MsgKey;
  final String MsgPic;

  const DashBoardBanner(
      {required this.MsgId, required this.MsgKey, required this.MsgPic});

  factory DashBoardBanner.fromJson(Map<String, dynamic> json) {
    return DashBoardBanner(
      MsgId: json['MsgId'] as String,
      MsgKey: json['MsgKey'] as String,
      MsgPic: json['MsgPic'] as String,
    );
  }
}

Future<List<DashBoardBanner>> getBannerDataFromServer() async {
  final queryParameters = {
    "ApiFunc": 'Banner',
    "UserKey": getDeviceKey(),
    "Token": getDeviceToken(),
    "SubmitContent": json.encode({"MobileNo": getMobileNo1()})
  };
  final response = await http.post(
    Uri.http('somesite.net', '/capi.aspx', queryParameters),
  );

  if (response.statusCode == 200) {
    Map<String, dynamic> data = jsonDecode(response.body);
    final splitoff = jsonEncode(data['RespContent']);
    return compute(parseBanner, splitoff);
  } else {
    throw Exception('Failed to load Data');
  }
}

List<DashBoardBanner> parseBanner(String responseBody) {
  final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
  return parsed
      .map<DashBoardBanner>((json) => DashBoardBanner.fromJson(json))
      .toList();
}

编辑:我重建了文件复制参考[1],它最终显示了我需要的数据,似乎问题源于没有返回 obj 的第二个小部件,但是怎么做我将第二个构建小部件组合到第一个小部件中,而不需要整个小部件,因为让整个构建小部件返回 1 行似乎毫无意义?

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:Container(
        child: FutureBuilder<List<DashBoardBanner>>(
          future: getBannerDataFromServer(http.Client()),
          builder: (context, snapshot) {
            if (snapshot.hasError) {
              return const Center(
                child: Text('An error has occurred!'),
              );
            } else if (snapshot.hasData) {
              print(snapshot.data!.length);
              return DashBoardBannersList(dashboardBanners: snapshot.data!);  <--- original issue due to not having this
            } else {
              return CircularProgressIndicator();
            }
          },
        ),
      ),

    );
  }
}

class DashBoardBannersList extends StatelessWidget {
  const DashBoardBannersList({Key? key, required this.dashboardBanners}) : super(key: key);

  final List<DashBoardBanner> dashboardBanners;

  @override
  Widget build(BuildContext context) {
        return Text(dashboardBanners[0].MsgId); 
  }
}

【问题讨论】:

    标签: flutter asynchronous flutter-futurebuilder


    【解决方案1】:

    您想检索 DashBoardBanner 列表,但忘记通过添加 ListView.builder() 来初始化 futurebuilder。

    尝试使用以下代码思路:

     FutureBuilder(
                future: getBannerDataFromServer(http.Client()),
                builder: (context, AsyncSnapshot snapshot) {
                  print(snapshot.hasData);
                  if (snapshot.hasError) {
                    return CircularProgressIndicator();
                  } else if (snapshot.hasData) {
                    return Expanded(
                      child: ListView.builder(
                          scrollDirection: Axis.vertical,
                          itemCount: snapshot.data!.length,
                           itemBuilder: (BuildContext context, int index) {
                            var data = snapshot.data![index];
                            return DashBoardBannersList(dashboardBanners: data);
                              },),
                             ),},
                           },)

    【讨论】:

      【解决方案2】:

      检查Firestore docs

      snapshot.data 内部,有docs(您收藏的每个文档)。

      代码来自那里:

        @override
        Widget build(BuildContext context) {
          return StreamBuilder<QuerySnapshot>(
            stream: _usersStream,
            builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
              if (snapshot.hasError) {
                return Text('Something went wrong');
              }
      
              if (snapshot.connectionState == ConnectionState.waiting) {
                return Text("Loading");
              }
      
              return ListView(
                children: snapshot.data!.docs.map((DocumentSnapshot document) {
                Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
                  return ListTile(
                    title: Text(data['full_name']),
                    subtitle: Text(data['company']),
                  );
                }).toList(),
              );
            },
          );
        }
      

      上面的代码展示了如何将每个文档(类型DocumentSnapshot)转换为JSON 格式(可以用Map&lt;String, dynamic&gt; 表示)。要访问文档id,您将使用document.id 进行访问,因为它不在document.data() 方法内。

      【讨论】:

        【解决方案3】:

        这个错误是因为声音空安全引起的

        对于某些请求,snapshot.data 可能为空,因此您无法访问某个索引处的数组,因为它可能为空。 如果您确定 snapshot.data 存在,您可以使用 !运算符告诉 dart 变量肯定不为空:

        snapshot.data![index];
        

        您还可以在访问之前检查数据是否为空:

        if (snapshot.data != null) {
            // do something with snapshot.data[index]
        }
        

        我建议阅读更多关于声音空安全here

        【讨论】:

        • 我明白了,谢谢!这应该可以解决索引的问题,但在我对此进行操作之前我仍然需要查看数据。
        猜你喜欢
        • 1970-01-01
        • 2021-11-17
        • 2020-04-12
        • 2020-07-20
        • 2020-03-08
        • 2019-05-31
        • 2021-12-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多