【问题标题】:List<dynamic> is not a subtype of type 'string' in type castList<dynamic> 不是类型转换中“字符串”类型的子类型
【发布时间】:2021-01-10 06:32:45
【问题描述】:

我正在尝试发布我的数据,其中包含一组 cartItems 和其他信息。但无法通过它。

laravel 的 api 生成如下 image

我对邮递员的要求

我在 logcat 中遇到以下错误:

   type 'List<dynamic>' is not a subtype of type 'String' in type cast

E/flutter (13443): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The getter 'statusCode' was called on null.
E/flutter (13443): Receiver: null
E/flutter (13443): Tried calling: statusCode
E/flutter (13443): #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
E/flutter (13443): #1      new ResponseApi (package:kitabyatra/response/ResponseApi.dart:11:21)
E/flutter (13443): #2      ContentRepositoryImpl.dopostApiCallWithToken (package:kitabyatra/repository/ContentRepositoryImpl.dart:184:41)
E/flutter (13443): <asynchronous suspension>
E/flutter (13443): #3      ContentRepositoryImpl.doAddOrderApiCall (package:kitabyatra/repository/ContentRepositoryImpl.dart:515:18)
E/flutter (13443): #4      CheckoutPresenter.doAddOrderApiCall (package:kitabyatra/view/checkout/CheckoutPresenter.dart:552:81)
E/flutter (13443): #5      CheckoutState._buildDeliveryLocation.<anonymous closure> (package:kitabyatra/view/checkout/CheckoutView.dart:303:35)
E/flutter (13443): #6      _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:993:19)
E/flutter (13443): #7      _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:1111:38)
E/flutter (13443): #8      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:183:24)
E/flutter (13443): #9      TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:598:11)
E/flutter (13443): #10     BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:287:5)
E/flutter (13443): #11     BaseTapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:259:7)
E/flutter (13443): #12     GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:157:27)
E/flutter (13443): #13     GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:362:20)
E/flutter (13443): #14     GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:338:22)
E/flutter (13443): #15     RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:267:11)
E/flutter (13443): #16     GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:295:7)
E/flutter (13443): #17     GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:240:7)
E/flutter (13443): #18     GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:213:7)
E/flutter (13443): #19     _rootRunUnary (dart:async/zone.dart:1206:13)
E/flutter (13443): #20     _CustomZone.runUnary (dart:async/zone.dart:1100:19)
E/flutter (13443): #21     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
E/flutter (13443): #22     _invoke1 (dart:ui/hooks.dart:265:10)
E/flutter (13443): #23     _dispatchPointerDataPacket (dart:ui/hooks.dart:174:5)

我的响应 API 类

    class ResponseApi {

  int code;
  String body;
  String errorMessage;

  ResponseApi(Response response)
  {
    code = response.statusCode;

    if (isSuccessful())
    {
      body = response.body;
      errorMessage = '';
    }
    else
    {
      body = response.body;
      errorMessage = "";
    }
  }

  bool isSuccessful()
  {
    return code >= 100 && code < 600;
  }
}

我已经实现了postcall方法如下:

 @override
  Future<ResponseFormat<ResponseAddOrder>> doAddOrderApiCall(
      Map<String, dynamic> map) async {
    final String url = liveUrl + "user/order/product";
    print("Add Order ");
    print(url);
    return await dopostApiCallWithToken<ResponseAddOrder, ResponseAddOrder>(
        ResponseAddOrder(), url, map);
  }

我的 post 方法处理如下:

@override
  Future<ResponseFormat<R>> dopostApiCallWithToken<T extends ResponseUni, R>(
      T obj, String url, Map map) async {
    Map valueMap = json.decode(JsonEncoder().convert(map));
    SecureStorageRepositoryImpl secureStorageRepositoryImpl =
        SecureStorageRepositoryImpl();
    String apiToken = await secureStorageRepositoryImpl.getApiToken();

    if (apiToken == null) {
      apiToken = "";
    }

    final Client client = http.Client();
    Map<String, String> requestHeaders = {'authorization': apiToken};
    try {
      final response = await http
          .post(
        '$url',
        headers: requestHeaders,
        body: valueMap,
      )
          .catchError((dynamic e) {
      
        print("${e.toString()}");
      });

print(response); ------>>> // Here I am getting null 

      final ResponseApi psApiResponse = ResponseApi(response);
      print(psApiResponse.errorMessage);
      print(psApiResponse.code);
      if (psApiResponse.isSuccessful()) {
        final dynamic hashMap = json.decode(response.body);

        if (!(hashMap is Map)) {
          final List<T> tList = <T>[];
          hashMap.forEach((dynamic data) {
            tList.add(obj.fromMap(data));
          });
          return ResponseFormat<R>(Status.SUCCESS, '', tList ?? R);
        } else {
          return ResponseFormat<R>(Status.SUCCESS, '', obj.fromMap(hashMap));
        }
      } else {
        return ResponseFormat<R>(
            Status.ERROR, psApiResponse.errorMessage, null);
      }
    } finally {
      client.close();
    }
  }

我已经按如下方式创建了我的请求类:

class RequestCheckOut extends RequestUni<RequestCheckOut> {
  RequestCheckOut({

    this.cartList,
    this.paymentId,
    this.price,
    this.deliveryAddressId,
    this.billingAddressId,
    this.discount,
    this.deliveryCharge,
    this.finalPrice,

  });
  var cartList;
  String paymentId;
  String price;
  String deliveryAddressId;
  String billingAddressId;
  String discount;
  String deliveryCharge;
  String finalPrice;



  @override
  RequestCheckOut fromMap(dynamic dynamicData) {
    if (dynamicData != null) {
      return RequestCheckOut(
        cartList : dynamicData['cartList'],
        paymentId : dynamicData['payment_id'],
        price : dynamicData['price'],
        deliveryAddressId : dynamicData['delivery_address_id'],
        billingAddressId : dynamicData['billing_address_id'],
        discount : dynamicData['discount'],
        deliveryCharge : dynamicData['delivery_charge_amt'],
        finalPrice : dynamicData['final_price'],


      );
    }
    else
    {
      return null;
    }
  }

  @override
  Map<String, dynamic> toMap()
  {
    var data = Map<String, dynamic>();

    data['cartList']=cartList;
    data['payment_id']=paymentId;
    data['price']=price;
    data['delivery_address_id']=deliveryAddressId;
    data['billing_address_id']=billingAddressId;
    data['discount']=discount;
    data['delivery_charge_amt']=deliveryCharge;
    data['final_price']=finalPrice;


    return data;
  }

  RequestCheckOut.fromJson(Map<String, dynamic> json) {

    cartList = (json['cartList']);
    paymentId = (json['payment_id']);
    price = (json['price']);
    deliveryAddressId = (json['delivery_address_id']);
    billingAddressId = (json['billing_address_id']);
    discount = (json['discount']);
    deliveryCharge = (json['delivery_charge_amt']);
    finalPrice = (json['final_price']);

  }
}

我从视图中调用了演示者,如下所示:

  RequestCheckOut requestCheckout = RequestCheckOut(
                          cartList:widget.cartList,
                          paymentId: presenter.responsePayment.value.data
                              .paymentMethod[_value].id
                              .toString(),
                          price: widget.totalPrice.toString(),
                          deliveryAddressId: presenter.responseAddress.value
                              .data.addressList[toggleIndex].id
                              .toString(),
                          billingAddressId: presenter.responseAddress.value.data
                              .addressList[toggleIndex].id
                              .toString(),
                          discount: "0",
                          deliveryCharge: widget.shipPrice.toString(),
                          finalPrice: widget.totalPrice.toString(),
                        );
                     
                        presenter.doAddOrderApiCall(requestCheckout);

我在presenter中实现了doAddOrderApiCall如下:

  doAddOrderApiCall(RequestCheckOut requestCheckOut) async
  {

    print("Do Add Order");
    view.showProgress();
    if (isConnectedToInternet)
    {
      print(requestCheckOut);
      final ResponseFormat<ResponseAddOrder> responseFormat = await contentRepo.doAddOrderApiCall(requestCheckOut.toMap());

      if(responseFormat.value.status)
      {

        view.hideProgress();
        view.showMessage(responseFormat.value.message);

        view.onBackPressed();

      }
      else
      {
        view.showMessage(responseFormat.value.message);
        view.hideProgress();
      }
    }
    else
    {

      view.hideProgress();
    }
  }

响应购物车列表

class ResponseCartList  extends ResponseUni<ResponseCartList>{
  bool status;
  String message;
  Data data;

  ResponseCartList({this.status, this.message, this.data});

  ResponseCartList.fromJson(Map<String, dynamic> json) {
    status = json['status'];
    message = json['message'];
    data = json['data'] != null ? new Data.fromJson(json['data']) : null;
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['status'] = this.status;
    data['message'] = this.message;
    if (this.data != null) {
      data['data'] = this.data.toJson();
    }
    return data;
  }

  @override
  fromMap(dynamicData) {
    if (dynamicData != null)
    {
      return ResponseCartList(
        status: dynamicData['status'],
        message: dynamicData['message'],
        data:dynamicData['data']!=null?Data.fromJson(dynamicData['data']):null,
      );
    }
    else
    {
      return null;
    }
  }

  @override
  String getPrimaryKey() {
   return '';
  }

  @override
  Map<String, dynamic> toMap(object) {
    {
      if (object != null)
      {
        final Map<String, dynamic> data = <String, dynamic>{};
        data['status'] = object.status;
        data['message'] = object.message;
        data['data'] = object.data!=null?object.data.toJson():null;
        return data;
      }
      else
      {
        return null;
      }
    }
  }
}

class Data {
  List<CartList> cartList;

  Data({this.cartList});

  Data.fromJson(Map<String, dynamic> json) {
    if (json['cart_list'] != null) {
      cartList = new List<CartList>();
      json['cart_list'].forEach((v) {
        cartList.add(new CartList.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    if (this.cartList != null) {
      data['cart_list'] = this.cartList.map((v) => v.toJson()).toList();
    }
    return data;
  }
}

class CartList {
  int id;
  int productQty;
  int productId;
  String productSlug;
  String productName;
  String mrpPaperBook;
  String listingPrice;
  String productImage;

  CartList(
      {this.id,
        this.productQty,
        this.productId,
        this.productSlug,
        this.productName,
        this.mrpPaperBook,
        this.listingPrice,
        this.productImage});

  CartList.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    productQty = json['product_qty'];
    productId = json['product_id'];
    productSlug = json['product_slug'];
    productName = json['product_name'];
    mrpPaperBook = json['mrp_paper_book'];
    listingPrice = json['listing_price'];
    productImage = json['product_image'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['id'] = this.id;
    data['product_qty'] = this.productQty;
    data['product_id'] = this.productId;
    data['product_slug'] = this.productSlug;
    data['product_name'] = this.productName;
    data['mrp_paper_book'] = this.mrpPaperBook;
    data['listing_price'] = this.listingPrice;
    data['product_image'] = this.productImage;
    return data;
  }
}

【问题讨论】:

  • 不要使用 var cartList 尝试使用它的类型 List 以避免不必要的动态
  • cartList 包含来自响应的数据
  • 什么样的数据?一个列表?是字符串类型的列表吗?
  • 购物车列表
  • 我想我不是在解释自己,var cartList 到底是什么类型的? 'CartList' 不是您在代码中显示的类,变量 cartList 是否试图保存字符串列表?如果是这种情况,而不是使用 var 将其更改为 List cartList 和 fromMap cartList : dynamicData['cartList'].?cast()

标签: flutter dart


【解决方案1】:
try {
  final response = await http
      .post(
    '$url',
    headers: requestHeaders,
    body: valueMap,
  ).catchError((dynamic e) { /// <-- somehting wrong happened here and is catched
  
    print("${e.toString()}");
  });

当发送 http 请求时,解析有一些错误,所以它被catchError 捕获,你打印的错误是:

type 'List<dynamic>' is not a subtype of type 'String' in type cast

因为响应为null,所以打印结果返回null,之后调用final ResponseApi psApiResponse = ResponseApi(response);第一行:

code = response.statusCode;

抛出其余的错误,因为响应为 null 并且无法从 null 对象调用 statusCode

E/flutter (13443): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The getter 'statusCode' was called on null.
E/flutter (13443): Receiver: null
E/flutter (13443): Tried calling: statusCode
.....

我仍然相信您的错误(这是某种解析)与您的 cartList 相关,您将其声明为 var cartList 并且 json.decode / encode 尝试按照它理解的方式解析它,如果您的cartList 是 List 但您将其声明为 var 它只会假定它是一个 List,您需要将其更改为正确的类型,以便解码器/编码器使用正确的 toJson/fromJson

class RequestCheckOut extends RequestUni<RequestCheckOut> {
  RequestCheckOut({

    this.cartList,
    this.paymentId,
    this.price,
    this.deliveryAddressId,
    this.billingAddressId,
    this.discount,
    this.deliveryCharge,
    this.finalPrice,

  });
  Data cartList;  // <---- Here use exactly the type of object you want to be encoded, Data, List<CartList> or ResponseCartList
  String paymentId;
  String price;
  String deliveryAddressId;
  String billingAddressId;
  String discount;
  String deliveryCharge;
  String finalPrice;



  @override
  RequestCheckOut fromMap(dynamic dynamicData) {
    if (dynamicData != null) {
      return RequestCheckOut(
        cartList : dynamicData['cartList'], // <--- Here try to use the correct fromJson/ fromMap instead of let the machine try it to guess it for you, because it will just decode it from the simplest objects, String, num, etc., if it's Data then use Data.fromJson(dynamicData['cartList'])
        paymentId : dynamicData['payment_id'],
        price : dynamicData['price'],
        deliveryAddressId : dynamicData['delivery_address_id'],
        billingAddressId : dynamicData['billing_address_id'],
        discount : dynamicData['discount'],
        deliveryCharge : dynamicData['delivery_charge_amt'],
        finalPrice : dynamicData['final_price'],


      );
    }
    else
    {
      return null;
    }
  }

  @override
  Map<String, dynamic> toMap()
  {
    var data = Map<String, dynamic>();

    data['cartList']=cartList;
    data['payment_id']=paymentId;
    data['price']=price;
    data['delivery_address_id']=deliveryAddressId;
    data['billing_address_id']=billingAddressId;
    data['discount']=discount;
    data['delivery_charge_amt']=deliveryCharge;
    data['final_price']=finalPrice;


    return data;
  }

  RequestCheckOut.fromJson(Map<String, dynamic> json) {

    cartList = (json['cartList']);
    paymentId = (json['payment_id']);
    price = (json['price']);
    deliveryAddressId = (json['delivery_address_id']);
    billingAddressId = (json['billing_address_id']);
    discount = (json['discount']);
    deliveryCharge = (json['delivery_charge_amt']);
    finalPrice = (json['final_price']);

  }
}

【讨论】:

  • 还是同样的问题
  • 我已经用在邮递员中发布数据的方法编辑了我的问题
  • 检查更新并在解码时尝试做一些调试,以确保对象真的是你想要的,尽可能避免使用 var 和 dynamic
【解决方案2】:

发布方法调用

    @override
  Future<ResponseFormat<ResponseAddOrder>> doAddOrderApiCall(
      RequestCheckOut requestCheckOut) async {
    final String url = liveUrl + "user/order/product";
    print("Add Order ");
    print(url);
    return await dopostOApiCallWithToken<ResponseAddOrder, ResponseAddOrder>(
        ResponseAddOrder(), url, requestCheckOut);
  }

修改post方式如下:

    @override
  Future<ResponseFormat<R>> dopostApiCallWithToken<T extends ResponseUni, R>(
    T obj,
    String url,
    var map,
  ) async {
    print(map);
    Map valueMap = json.decode(JsonEncoder().convert(map));
    var value = json.encode(map);

    print("Map value");

    print(value);

    SecureStorageRepositoryImpl secureStorageRepositoryImpl =
        SecureStorageRepositoryImpl();
    String apiToken = await secureStorageRepositoryImpl.getApiToken();

    if (apiToken == null) {
      apiToken = "";
    }

    final Client client = http.Client();

    Map<String, String> requestHeaders = {
      "Content-type": "application/json",
      "Authorization": apiToken

    };
    try {
      final response = await http
          .post(
        '$url',
        headers: requestHeaders,
        body: value,
      )
          .catchError((dynamic e) {
        print("Error");
        print("${e.toString()}");
      });
      print("Response");
      print(response.statusCode);
      print(json.decode(response.body));

      final ResponseApi psApiResponse = ResponseApi(response);
      print(psApiResponse.errorMessage);
      print(psApiResponse.code);
      if (psApiResponse.isSuccessful()) {
        final dynamic hashMap = json.decode(response.body);
        if (!(hashMap is Map)) {
          print("hash");
          print(hashMap);
          final List<T> tList = <T>[];
          hashMap.forEach((dynamic data) {
            tList.add(obj.fromMap(data));
            print("tList");
            print(tList);
          });
          return ResponseFormat<R>(Status.SUCCESS, '', tList ?? R);
        } else {
          return ResponseFormat<R>(Status.SUCCESS, '', obj.fromMap(hashMap));
        }
      } else {
        print("Error");
        return ResponseFormat<R>(
            Status.ERROR, psApiResponse.errorMessage, null);
      }
    } finally {
      client.close();
    }
  }

【讨论】:

    猜你喜欢
    • 2021-10-20
    • 2019-12-31
    • 2021-10-23
    • 2020-12-21
    • 2021-05-08
    • 2019-01-13
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多