我创建了一个用于处理请求的http服务,并做出了通用响应。它在将Generic作为基元传递时起作用,但在传递List(甚至是动态的(时,它会在赋值过程中抛出错误。稍后跳过键入和强制转换也不起作用。我被难住了。
class Room {
final String name;
const Room({required this.name});
}
List<Room> ownRoomsList = [];
List<dynamic> savedRooms = [];
Future<void> updateRooms() async {
HttpService httpService = new HttpService();
await httpService.init();
final response = await httpService.request<List<Room>>(
url: "puff/rooms", method: Method.POST);
if (response != null) {
setState(() {
ownRoomsList = response.data; // Error here.
});
}
}
class APIResponse<T> {
final bool success;
final T data;
final String message;
const APIResponse(
{required this.success, required this.data, required this.message});
factory APIResponse.fromJson(Map<String, dynamic> json) {
return APIResponse(
success: json['success'],
data: json['data'],
message: json['message'],
);
}
}
class HttpService<T> {
Dio? _dio;
var logger = Logger(
printer: PrettyPrinter(),
);
Future<HttpService> init() async {
SharedPreferences pref = await SharedPreferences.getInstance();
final userId = pref.getInt('userId');
final headers = {
"Content-Type": "application/json",
"userId": userId.toString()
};
_dio = Dio(BaseOptions(baseUrl: BASE_URL, headers: headers));
initInterceptors();
return this;
}
void initInterceptors() {
_dio!.interceptors.add(
InterceptorsWrapper(
onRequest: (requestOptions, handler) {
logger.i(
"REQUEST[${requestOptions.method}] => PATH: ${requestOptions.path}"
"=> REQUEST VALUES: ${requestOptions.queryParameters}"
"=> POST VALUES: ${requestOptions.data}"
"=> HEADERS: ${requestOptions.headers}");
return handler.next(requestOptions);
},
onResponse: (response, handler) {
logger
.i("RESPONSE[${response.statusCode}] => DATA: ${response.data}");
return handler.next(response);
},
onError: (err, handler) {
logger.i("Error[${err.response?.statusCode}]");
return handler.next(err);
},
),
);
}
Future<APIResponse<T>?> request<T>(
{required String url,
required Method method,
Map<String, dynamic>? params}) async {
Response response;
try {
if (method == Method.POST) {
response = await _dio!.post(url, data: params);
} else if (method == Method.DELETE) {
response = await _dio!.delete(url);
} else if (method == Method.PATCH) {
response = await _dio!.patch(url);
} else {
response = await _dio!.get(url, queryParameters: params);
}
if (response.statusCode == 200) {
return APIResponse.fromJson(jsonDecode(response.data));
} else if (response.statusCode == 401) {
//throw Exception("Unauthorized");
} else if (response.statusCode == 500) {
//throw Exception("Server Error");
} else {
//throw Exception("Something went wrong");
}
} on SocketException catch (e) {
logger.e(e);
//throw Exception("No Internet Connection");
} on FormatException catch (e) {
logger.e(e);
//throw Exception("Bad response format");
} on DioError catch (e) {
logger.e(e);
//throw Exception(e);
} catch (e) {
logger.e(e);
//throw Exception("Something went wrong");
}
return null;
}
}
错误:
type 'List<dynamic>' is not a subtype of type 'List<Room>'
碰巧,Dart不支持非基元的动态类型,因此内部的强制转换从未工作过。首先,需要在类型中添加一个fromJson
,将httpService.request<List<Room>>
更改为httpService.request<List<dynamic>>
,然后将答案从ownRoomsList = response.data;
处理为ownRoomsList = response.data.map((e) => Room.fromJson(e)).toList();
class Room {
final String name;
const Room({required this.name});
factory Room.fromJson(Map<String, dynamic> json) {
return Room(name: json['name']);
}
}