Flutter FutureBuilder 返回空数据

Posted

技术标签:

【中文标题】Flutter FutureBuilder 返回空数据【英文标题】:Flutter FutureBuilder returning null data 【发布时间】:2020-03-08 16:47:25 【问题描述】:

我是 Flutter 和 Dart 的新手,我正在尝试编写一个应用程序来测试它。 我有一个 api,我正在获取应用程序的数据,并尝试使用 StatefulWidget 和 FutureBuilder。

当我运行调用 api 的方法时,我得到了结果(使用 print() 来测试它),但是当我从 loadData 方法获取数据时,它会返回 null。

所以 loadData 打印数据,initState 和 FutureBuilder 数据返回 null。我在这里错过了什么。

我已添加用于请求的服务和模型...希望对您有所帮助。

Future<CoachesModelRes> loadData(Profile _profile) async 
await getPost(_profile.getToken()).then((response) 
  if (response.statusCode == 200) 
    CoachesModelRes coaches = coachesModel.postFromJson(response.body);

    if (coaches.count > 0) 
      print(coaches.count);
      print(coaches.coaches[0].description);
      return coaches;
     else 
      return null;
    
   else 
    String code = response.statusCode.toString();
    return null;
  
).catchError((error) 
  print(error.toString());
  return null;
);


@override
void initState() 
  super.initState();
  print(widget.profile.getToken());
  data = loadData(widget.profile);
  data.then((data_) async 
    var cenas = data_.count;
    print("asdasd $cenas");
  );


Future<CoachesModelRes> data;

@override
Widget build(BuildContext context) 
  return Scaffold(
    backgroundColor: appWhiteColor,
  appBar: applicationBar(),
  drawer: adminDrawer(widget.profile, AdminDrawerListEnum.coaches, context),
  body: FutureBuilder<CoachesModelRes>(
    future: data,
    builder: (context, snapshot) 
      //print(snapshot.data.count.toString());
      if (snapshot.hasData) 
        return Text("nop");
       else if (snapshot.hasError) 
        return Text("$snapshot.error");
      
      return Text("nop");
      // By default, show a loading spinner.
      return CircularProgressIndicator();
    ,
  ),
);


Future<http.Response> getPost(String token) async 
   final response = await http.get(new Uri.http("$apiUrl", "$coachesEndPoint"),
     headers: 
      HttpHeaders.contentTypeHeader: 'application/json',
      HttpHeaders.authorizationHeader : 'Bearer $token'
     ,
  );
  return response;



CoachesModelRes postFromJson(String str) => CoachesModelRes.fromJson(json.decode(str));

class CoachesModelRes 

 int count;
 List<CoachModelRes> coaches;

 CoachesModelRes(
    this.count,
    this.coaches,
 );

 factory CoachesModelRes.fromJson(Map<String, dynamic> json) => new CoachesModelRes(
    count: json["count"],

    coaches: (json["coaches"] as List).map((i) => CoachModelRes.fromJson(i)).toList(),
 );



CoachModelRes postFromJson(String str) => CoachModelRes.fromJson(json.decode(str));

class CoachModelRes 

    String id;
    String firstName;
    String lastName;
    String description;
    String username;
    String notes;
    List<String> roles;

    CoachModelRes(
        this.id,
        this.firstName,
        this.lastName,
        this.description,
        this.username,
        this.notes,
        this.roles,
    );

    factory CoachModelRes.fromJson(Map<String, dynamic> json) => new CoachModelRes(
        id: json["id"],
        firstName: json["firstName"],
        lastName: json["lastName"],
        description: json["description"],
        username: json["username"],
        notes: json["notes"],
        roles: new List<String>.from(json["roles"]),
    );

【问题讨论】:

如果我不是必须的,我在这里遇到的问题是我最后没有在 loadData 方法中返回数据。我正在构建其他应用程序,并以不同的方式工作。我会在几天后更新此内容,并提供有效回复。 【参考方案1】:
 Future<CoachesModelRes> loadData(Profile _profile) async 
     final response = await  getPost(_profile.getToken());
    tryif (response.statusCode == 200) 
    CoachesModelRes coaches = coachesModel.postFromJson(response.body);
    if (coaches.count > 0) 
      print(coaches.count);
      print(coaches.coaches[0].description);
      return coaches;
     else 
      return null;
    
   else 
    String code = response.statusCode.toString();
    return null;
  catch(e)

    return null ; 
  
    
@override
void initState() 
  super.initState();



@override
Widget build(BuildContext context) 
  return Scaffold(
    backgroundColor: appWhiteColor,
  appBar: applicationBar(),
  drawer: adminDrawer(widget.profile, AdminDrawerListEnum.coaches, context),
  body: FutureBuilder<CoachesModelRes>(
    future: loadData(widget.profile),
    builder: (context, snapshot) 
      //print(snapshot.data.count.toString());
      if (snapshot.hasData) 
        return Text("nop");
       else if (snapshot.hasError) 
        return Text("$snapshot.error");
      
      return Text("nop");
      // By default, show a loading spinner.
      return CircularProgressIndicator();
    ,
  ),
);

【讨论】:

这样返回null。我只是让它工作清除:'CoachesModelRes 数据;'并在 loadData 方法设置'data = coaches;'然后使用数据创建小部件。 你现在可以试试吗 要使用 FutureBuilder,var 数据必须是 Future 而不是 CoachesModelRes...如果我更改它,它会返回 null。 我明白了 仍然为空,找不到解决办法。【参考方案2】:

这里的问题是 return 语句应该在方法的末尾。

因为getPost会将数据返回给loadData

getPost 完成时,loadData 会将数据返回给调用他的方法。

在我的情况下,loadData 没有返回任何内容,因此FutureBuilder 中的snapshot 始终为空。

现在是这样的逻辑,但当时我想不通:\

Future<CoachesModelRes> loadData(Profile _profile) async 
// So I need to create a variable to return
CoachesModelRes response;
//-----
await getPost(_profile.getToken()).then((response) 
  if (response.statusCode == 200) 
    CoachesModelRes coaches = coachesModel.postFromJson(response.body);

       if (coaches.count > 0) 
         print(coaches.count);
         print(coaches.coaches[0].description);
         // Set the variable value
         response = coaches;
         //-----
        else 
         // Set the variable value
         response = null;
         //-----
       
      else 
       String code = response.statusCode.toString();
       // Set the variable value
       response = null;
       //-----
     
   ).catchError((error) 
     print(error.toString());
     // Set the variable value
     response = null;
     //-----
   );
   // And at the end return the response variable
   return response;
   //-----

【讨论】:

以上是关于Flutter FutureBuilder 返回空数据的主要内容,如果未能解决你的问题,请参考以下文章

使用 Mockito 的 FutureBuilder 快照数据为空 - Flutter

Flutter + SharedPreferences:如何使用 FutureBuilder

为啥 futureBuilder 返回一个空值?

FlutterFuture 与 FutureBuilder 异步编程代码示例 ( FutureBuilder 构造函数设置 | 处理 Flutter 中文乱码 | 完整代码示例 )

Flutter:不清楚 ValueChanged 和 FutureBuilder

FutureBuilder 错误:返回类型“对象?”不是闭包上下文所要求的“小部件”