【问题标题】:type 'List<dynamic>' is not a subtype of type 'List<Todo>''List<dynamic>' 类型不是 'List<Todo>' 类型的子类型
【发布时间】:2021-06-24 10:25:54
【问题描述】:

我使用 dio 和 getx 来获取 todo 数据列表,但我看到了这条消息

type 'List&lt;dynamic&gt;' is not a subtype of type 'List&lt;Todo&gt;'

当我到达这条线时

List responseBode = rsp.data['data'];

这行发生了什么以及如何解决它,谢谢

通过转换为列表更新了服务类,但仍然是同样的问题

1- 控制器的第一类 2-服务类的第二个

class TodoListController extends GetxController {
  //var lstTask = List<dynamic>.empty(growable: true).obs;
  var items = List<Todo>.empty(growable: true).obs;

  var page = 1.obs;
  var totalRows = 10.obs;
  var isDataProcessing = false.obs;
  var isMoreDataAvailable = true.obs;
  var isSearching = false.obs;
  var isLoading = false.obs;
  var isCompleted = true.obs;

  var errorMsg = ''.obs ;
  var http = new HttpUtils();

  // For Pagination
  ScrollController scrollController = ScrollController();

  @override
  onInit() {
    super.onInit();
    // Fetch Data
    getTodo(page);

  }

  // Fetch Data
   getTodo(var page) {
    try {
      isMoreDataAvailable(false);
      isDataProcessing(true);
      AppServices().getTodo(page).then((resp) {
        isDataProcessing(false);
        resp.forEach(( dynamic json) {
          items.add(Todo.fromJson(json));
        });
        print(resp);
        //items.addAll(resp);
      }, onError: (err) {
        isDataProcessing(false);
        AppServices().showSnackBar("Error", err.toString(), Colors.red);
      });
    } catch (exception) {
      isDataProcessing(false);
      AppServices().showSnackBar("Exception", exception.toString(), Colors.red);
    }
  }

  // Get More data
   getMoreTodo(var page) {
    try {
        AppServices().getTodo(page).then((resp) {
        if (resp.length > 0) {
          isMoreDataAvailable(true);
        } else {
          isMoreDataAvailable(false);
          AppServices().showSnackBar("Message", "No more items", Colors.lightBlueAccent);
        }
        items.addAll(resp);
      }, onError: (err) {
        isMoreDataAvailable(false);
        AppServices().showSnackBar("Error", err.toString(), Colors.red);
      });
    } catch (exception) {
      isMoreDataAvailable(false);
      AppServices().showSnackBar("Exception", exception.toString(), Colors.red);
    }
  }
}

   

类 AppServices 扩展 GetConnect { var http = new HttpUtils();

          // Fetch Data
  Future<List<Todo>> getTodo(var id) async {
    try {
      Response rsp =  await http.get(AppUrl.get_todo, {'current_page': id});
      print(rsp.data['data']);
      if (rsp.data["response_status"] != '400') {
        List<Todo> responseBode = rsp.data['data'].map ((todo) => Todo.fromJson(todo)).toList();
        return responseBode;
      } else {
        return rsp.data["response_message"] ;
      }
    }catch(exception)
    {
      return Future.error(exception.toString());
    }
  }
}

【问题讨论】:

    标签: flutter dart dio flutter-getx


    【解决方案1】:

    这可以通过简单的类型转换来解决。我注意到您正在使用 DioGetConnect。这本身没什么问题,但我无法想象你为什么需要两者。

    既然您已经在 GetX 世界中,这就是使用 GetConnect 的样子。这就是我可以测试的方式,因为我不确定HttpUtils 来自哪里。

    class AppServices extends GetConnect {
      // var http = new HttpUtils();
    
      // Fetch Data
      Future<List<Todo>> getTodo(var id) async {
        try {
          Response rsp = await httpClient.get(AppUrl.get_todo, {'current_page': id});
          print(rsp.body['data']);
          if (rsp.statusCode != 400) {
            List<Todo> responseBode = rsp.body['data'] as List<Todo>; // casting type here
            return responseBode;
          } else {
            return rsp.body["response_message"];
          }
        } catch (exception) {
          return Future.error(exception.toString());
        }
      }
    }
    

    如果这不起作用

    List<Todo> responseBode = rsp.body['data'] as List<Todo>; // casting type here
    

    那么你也可以使用 return Future&lt;List&gt; 代替。

    那么这会将上一行变成这个

    List responseBode = rsp.body['data'];
    
    

    GetConnect 为您处理 json 解码,因此在使用它时,您无需再手动执行任何 json 工作。

    编辑:在 cmets 中回答您关于在 GetConnect 中向标头添加身份验证的问题:

    你可以这样做。

    final url = 'http://...'
     void _setUrl() {
        httpClient.baseUrl = url;
        httpClient.addRequestModifier((request) {
          request.headers['apikey'] = yourApiKey;
          return request;
        });
      }
    

    之后你就可以打电话了

    final response = await httpClient.get(url);
    

    您的密钥将在 url 中。

    然后它会返回一个常规地图,你就可以开始了。

    【讨论】:

    • 谢谢,但如果删除此行,则此行不起作用,因为它是 dio 包装器,var http = new HttpUtils();我使用 dio 是因为我有两个关于 getconnect 的问题,但互联网上没有一个示例,尽管我 google 了它,1-如何将基本身份验证添加到标头,2-如何将许多参数传递给同一个请求
    • 正如你在这里看到的,我有能力通过这个 get(AppUrl.get_todo, {'current_page': id}) 它将转换为example.com/todo_list?current_page=1
    • json 库返回一个不能自动转换为类的映射,您需要一个命名构造函数。至少据我所知。
    • @Ale 抱歉,我应该澄清一下,json 注释是特定于 GetConnect 的,它会解码 json 本身并返回常规映射。为了清楚起见,我会更新答案。 @user1080247 看起来您有一个解决方案,但请参阅有关使用 GetConnect 在标头中添加身份验证的更新答案。我同意关于它的信息很少。
    【解决方案2】:

    你可以在没有 Dio 的情况下使用 GetConnect。

    您的 AppService 看起来像:

    Future<List<Todo>> getTodo(var id) async {
      final response =  await http.get(AppUrl.get_todo, query:{'current_page': id}, decoder: Todo.listFromJson);
      if(response.hasError){
        return Future.error(response.statusText);
       }
      return response.body;
    }
    

    您的模型将如下所示:

    class Todo {
     String name;
      Todo.fromJson (data) {
          name = data["name"] ?? null;
        }
    
     static List<Todo> listFromJson(dynamic str) => List<Todo>.from((str as List<dynamic>).map((x) => Todo.fromJson(x)));
    }
    

    现在它将直接返回 Todo 对象列表。

    用法可能是这样的(在控制器中):

    final todoList = <Todo>[].obs; 
    
    onInit()async{
     ...
     await getTodos();
    }
    
    Future<void> getTodos()async{
      try{
         final todos=await appServices.getTodo(1);
         todoList.assignAll(todos);
       } catch (e){
        // handle errors here. eg. show snackbar
       }
    

    【讨论】:

      【解决方案3】:

      问题是dynamic 的列表无法自动转换为Todo 的列表。 您可以像这样转换列表:

       List<Todo> responseBode = rsp.data['data'].map ((todo) => Todo.fromJson(todo)).toList();
      

      然后你可以像这样实现 Todo 命名构造器:

      class Todo {
           //Your todo class
           String name;
            Todo.fromJson (data) {
                // conversion here
                name = data["name"] ?? null;
          }
      }
      

      【讨论】:

      • 还是一样,还是一样的异常
      • 你能发布更新版本的代码吗?
      • 我还有一个待办事项模型
      猜你喜欢
      • 1970-01-01
      • 2021-12-29
      • 2023-01-08
      • 2021-07-06
      • 2021-02-17
      • 2018-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多