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

Posted

技术标签:

【中文标题】REST GET 在 Future Builder 中返回无效参数【英文标题】:REST GET is returning invalid arguments in Future Builder 【发布时间】:2021-01-18 01:24:20 【问题描述】:

我正在使用 Rest API 调用 GET 方法来获取一些数据。我这样做是为了加载一个配置文件以在我的颤动体内查看。我正在尝试将这些数据分配给 FutureBuilder 方法中的字符串变量。 在未来的 builder 中,应该返回 fetchUser() API 调用响应,但快照返回 null。因此,每当我尝试运行它时,屏幕都会卡在 CircularProgressIndicator 中。 有人可以帮我弄清楚我做错了什么以及如何解决它?

flutter 页面中的正文

final userProfileView = FutureBuilder<UserFetch>(
        future: CallApi().fetchUser(apiUrl),
        builder: (context, snapshot) 
          if(!snapshot.hasData)//(!snapshot.hasData)
            return Center(
              widthFactor: 120.0,
              heightFactor: 120.0,
              child: CircularProgressIndicator(),
            );
            // final userD = snapshot.data;
            _userName = snapshot.data.user.username.toString();
            _userEmail = snapshot.data.user.email;
            _userAddress = snapshot.data.user.address.toString();
            _userPassword = 'password';
            _userCountry = 'country';
            _userMobile = snapshot.data.user.mobile.toString();
            //checks if the response returns valid data
            return Container(
              child: Padding(
                padding:
                    const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
                child: SingleChildScrollView(
                  child: Column(
                    children: <Widget>[
                      userTitle,
                      SizedBox(height: 12.0),
                      userNameTitle,
                      userName,
                      SizedBox(height: 12.0),
                      userEmailTitle,
                      userEmail,
                      SizedBox(height: 12.0),
                      userPasswordTitle,
                      userPassword,
                      SizedBox(height: 12.0),
                      userAddressTitle,
                      userAddress,
                      SizedBox(height: 12.0),
                      userCountryTitle,
                      userCountry,
                      SizedBox(height: 12.0),
                      userPhoneTitle,
                      userPhone,
                      SizedBox(height: 24.0),
                      userLogoutBtn,
                    ],
                  ),
                ),
              ),
            );
          //  else if (snapshot.hasError) 
          //   //checks if the response throws an error
          //   return Text("$snapshot.error");
          // 
        );

API 调用

Future<UserFetch> fetchUser(apiUrl) async 
    var fullUrl = _baseUrl + apiUrl;
    final response = await http.get(fullUrl, headers: _setHeaders());

    if (response.statusCode == 200) 
      // If the call to the server was successful (returns OK), parse the JSON.
      return UserFetch.fromJson(json.decode(response.body));
     else 
      // If that call was not successful (response was unexpected), it throw an error.
      throw Exception('Failed to load User');
    
  

响应模型

UserFetch userFetchFromJson(String str) => UserFetch.fromJson(json.decode(str));

String userFetchToJson(UserFetch data) => json.encode(data.toJson());

class UserFetch 
  UserFetch(
    this.success,
    this.user,
  );

  bool success;
  User user;

  factory UserFetch.fromJson(Map<String, dynamic> json) => UserFetch(
    success: json["success"],
    user: User.fromJson(json["user"]),
  );

  Map<String, dynamic> toJson() => 
    "success": success,
    "user": user.toJson(),
  ;


class User 
  User(
    this.email,
    this.address,
    this.imperial,
    this.mobile,
    this.petsInfo,
    this.role,
    this.subscribed,
    this.username,
  );

  String email;
  String address;
  bool imperial;
  String mobile;
  List<PetsInfo> petsInfo;
  String role;
  bool subscribed;
  String username;

  factory User.fromJson(Map<String, dynamic> json) => User(
    email: json["email"],
    address: json["address"],
    imperial: json["imperial"],
    mobile: json["mobile"],
    petsInfo: List<PetsInfo>.from(json["pets_info"].map((x) => PetsInfo.fromJson(x))),
    role: json["role"],
    subscribed: json["subscribed"],
    username: json["username"],
  );

  Map<String, dynamic> toJson() => 
    "email": email,
    "address": address,
    "imperial": imperial,
    "mobile": mobile,
    "pets_info": List<dynamic>.from(petsInfo.map((x) => x.toJson())),
    "role": role,
    "subscribed": subscribed,
    "username": username,
  ;


class PetsInfo 
  PetsInfo(
    this.id,
    this.name,
  );

  int id;
  String name;

  factory PetsInfo.fromJson(Map<String, dynamic> json) => PetsInfo(
    id: json["id"],
    name: json["name"],
  );

  Map<String, dynamic> toJson() => 
    "id": id,
    "name": name,
  ;


调用用户个人资料页面时的日志


════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
'package:flutter/src/widgets/framework.dart': Failed assertion: line 273 pos 18: '_registry.containsKey(key)': is not true.
════════════════════════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following assertion was thrown while finalizing the widget tree:
'package:flutter/src/widgets/framework.dart': Failed assertion: line 273 pos 18: '_registry.containsKey(key)': is not true.


Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
  https://github.com/flutter/flutter/issues/new?template=BUG.md

When the exception was thrown, this was the stack: 
#2      GlobalKey._debugVerifyIllFatedPopulation.<anonymous closure> (package:flutter/src/widgets/framework.dart:273:18)
#3      GlobalKey._debugVerifyIllFatedPopulation (package:flutter/src/widgets/framework.dart:298:6)
#4      BuildOwner.finalizeTree.<anonymous closure> (package:flutter/src/widgets/framework.dart:2769:21)
#5      BuildOwner.finalizeTree (package:flutter/src/widgets/framework.dart:2849:8)
#6      WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:915:18)

【问题讨论】:

【参考方案1】:

使用未来类型来 API 调用函数,因为它不确定未来会发生什么

Future<dymamic> fetchUser(apiUrl) async 
    var fullUrl = _baseUrl + apiUrl;
    final response = await http.get(fullUrl, headers: _setHeaders());

    if (response.statusCode == 200) 
      // If the call to the server was successful (returns OK), parse the JSON.
      return UserFetch.fromJson(json.decode(response.body));
     else 
      // If that call was not successful (response was unexpected), it throw an error.
      throw Exception('Failed to load User');
    
  

现在检查FutureBuiler 中的响应是否引发错误。

if(snapshot.data=="Failed to load User")
   return Text("something went wrong");

【讨论】:

没有任何变化,仍然没有响应。我卡在屏幕上运行的圆形进度条中。 我把日志放在上面。当我尝试这样做时。 apiUrl = '用户/获取?user_email=$userEmail&user_token=$userToken'; var response = await http.get(apiUrl, headers: _setHeaders());打印(' - - - - - - - - - - - - - ');打印(response.toString());它无法打印('------------------------');不设置响应变量。 什么是_setHeaders()? 设置标题 _setHeaders() => 'Content-type': 'application/json', 'Accept': '/', ; 没有令牌吧?删除 headers 参数,然后尝试确保此 API 在邮递员中正常工作,并且不需要任何令牌或授权。

以上是关于REST GET 在 Future Builder 中返回无效参数的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Future.Builder 中的快照从不出错?

无法在Future Builder中显示解析的JSON

如何使用 Flutter 数据模型和 Future Builder

Spring REST 和 Future 任务

Flutter 'map' 动态调用 null。接收方:'_Future<dynamic>' 的实例 参数:['(dynamic) => Builder' 的实例]

Flutter + Hive 检查 Future Builder 的框中是不是存在值