Flutter Snapshot 为空,但来自 api 的响应不是

Posted

技术标签:

【中文标题】Flutter Snapshot 为空,但来自 api 的响应不是【英文标题】:Flutter Snapshot is null but response from api is not 【发布时间】:2021-10-25 18:53:02 【问题描述】:

我正在尝试使用从 api 获取的用户信息填充 ListView。我的 snapShot.data 总是错误的,但是当我记录我的 api 响应时,它会显示:

"id":"008","IndexNo":"00000","Name":"JOHN DOE  OCHIENG","IdNumber":"000000","PassportNumber":"","BirthCertNo":"","registration":["reg_no":"0000","cadre":"KEN","cadre_text":"KENYA ENROLLED NURSE","reg_no":"0000","cadre":"KEM","cadre_text":"KENYA ENROLLED MIDWIFE","reg_no":"0000","cadre":"KECHN (PB)","cadre_text":"KENYA ENROLLED  COMMUNITY HEALTH NURSE [PB]"]

这就是我尝试构建列表视图的方式:

class UserProfileScreen extends StatefulWidget 
  const UserProfileScreen(Key key) : super(key: key);

  @override
  _UserProfileScreenState createState() => _UserProfileScreenState();


class _UserProfileScreenState extends State<UserProfileScreen> 
  //a variable of type future to hold the array of posts returned
  Future<List<User>> _user;
  //variable for holding search data
  String searchString = "";
  //controller to feed into the search string
  final TextEditingController editingController = new TextEditingController();

  //overided the initState method to allow the getPosts method to be run onCreate
  void initState() 
    _user = getUser();
    super.initState();
  

  @override
  Widget build(BuildContext context) 
    double screenWidth = MediaQuery.of(context).size.width;
    double screenHeight = MediaQuery.of(context).size.height;
    return Scaffold(
      drawer: AppDrawer(),
      appBar: AyaAppBar(),
      body: WillPopScope(
          onWillPop: () async 
            Navigator.pop(context);
          ,
          child: NotificationListener<OverscrollIndicatorNotification>(
              onNotification: (OverscrollIndicatorNotification overScroll) 
                overScroll.disallowGlow();
                return true;
              ,
              //future builder of type <List<User>> to asynchronously list all the posts
              child: new FutureBuilder<List<User>>(
                  future: _user,
                  builder: (context, snapshot) 
                    if (snapshot.hasData == null) 
                      return Text('No data available');
                     else if (snapshot.hasError) 
                      return Text("$snapshot.error");
                     else 
                      List<User> myUser = snapshot.data;
                      var x = snapshot.hasData;
                      print("here $myUser");
                      return new ListView.builder(
                          itemCount: myUser.length,
                          itemBuilder: (BuildContext context, int index) 
                            //TO-DO: add a search widget to allow searches of the various posts
                            return myUser[index].indexNo.contains(searchString)
                                ? Card(
                                    child: Column(
                                      children: [
                                        ListTile(
                                          enabled: true,
                                          onTap: () ,
                                          title: Text(
                                              myUser[index].name.toString()),
                                          subtitle: Text(myUser[index]
                                              .idNumber
                                              .toString()),
                                        )
                                      ],
                                    ),
                                  )
                                : Container();
                          );
                    
                    return CircularProgressIndicator();
                  ))),
    );
  


//function that returns a list of posts
Future<List<User>> getUser() async 
  var url = Uri.parse('https://xx-api.xxxxxxx.co.ke/api/auth/user');
  var jwt = Globals.token;

  //todo add a try and catch on this http get request, also check internet connection
  var response = await http
      .get(url, headers: HttpHeaders.authorizationHeader: "Bearer $jwt");
  print(response.body);
  return List<User>.from(
      json.decode(response.body).map((x) => User.fromJson(x)));

我的模特:

import 'dart:convert';

List<User> userFromJson(String str) => List<User>.from(json.decode(str).map((x) => User.fromJson(x)));

String userToJson(List<User> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class User 
    User(
        this.indexNo,
        this.name,
        this.idNumber,
        this.passportNumber,
        this.birthCertNo,
    );

    String indexNo;
    String name;
    int idNumber;
    int passportNumber;
    int birthCertNo;

    factory User.fromJson(Map<String, dynamic> json) => User(
      indexNo: json["IndexNo"],
      name: json["Name"],
      idNumber: json["IdNumber"],
      passportNumber: json["PassportNumber"],
      birthCertNo: json["BirthCertNo"],
    );

    Map<String, dynamic> toJson() => 
      "indexNo": indexNo,
      "Name": name,
      "IdNumber": idNumber,
      "PassportNumber": passportNumber,
      "BirthCertNo": birthCertNo,
    ;


我的问题是,虽然 getUser() 似乎返回了有效数据,但 FutureBuilder 小部件中的语句 snapshot.hasdata 总是为 false。

这里出了什么问题?

【问题讨论】:

@RavindraS.Patil 谢谢,我得到了你的答案之一 最欢迎@tharnos_nos 你能告诉我哪个答案对你有用,请点赞。 【参考方案1】:

试试

返回列表.from( json.decode(response.body).map((x) => User.fromJson(x)).toList());

【讨论】:

以上是关于Flutter Snapshot 为空,但来自 api 的响应不是的主要内容,如果未能解决你的问题,请参考以下文章

Flutter Snapshot.hasData 总是返回 true

StreamBuilder总是在flutter中的print(snapshot.hasData)中返回false

使用所有类型的返回数据返回 null 值 Flutter

Flutter FutureBuilder 小部件动态列表长度

来自完整开发人员指南课程 Udemy 165 的 Flutter Bloc 模式问题

Flutter Firestore:未为类“Object?”定义运算符“[]”。 - “对象”来自“飞镖:核心”