我正在学习使用包 DIO https://pub.dev/packages/dio通过ID搜索数据,我的问题是每次我键入错误的关键字搜索时,应用都会突然崩溃,并显示调试消息找不到404 。
enter image description here
我知道找不到数据,因为我输入了错误的关键字,但是我已经可以使用此代码
Widget _searchKeywordMahasiswa() {
return FutureBuilder<List<Mosque>>(
future: api.getMahasiswaById(_searchText),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Text(snapshot.data[index].id);
},
),
);
} else if (!snapshot.data) { <<<<<< IN THIS LINE
return Center(
child: Icon(
Icons.sentiment_very_dissatisfied,
size: 150.0,
),
);
}
return CircularProgressIndicator();
},
);
// return CircularProgressIndicator();
}
Future<List<Mosque>> getMahasiswaById(String id) async{
try {
var apiRespon = await dio.get('${Urls.BASE_API_URL}/mahasiswa/get/id/$id');
var apiResponJson = apiRespon.data;
print(apiResponJson);
return (apiResponJson['data'] as List).map((p)=>Mosque.fromJson(p)).toList();
}on DioError catch (e) { <<<<< IN THIS LINE
if(e.response.statusCode == 404){
print(e.response.statusCode);
}else{
print(e.message);
print(e.request);
}
}
}
在同一情况下,如果我遇到错误 400错误的请求,我的应用程序也会崩溃,并且我已经处理了此错误,但无法正常工作。
您能帮我吗?
谢谢。
答案 0 :(得分:4)
我遇到了同样的问题,只是改变了我的拦截器工作
import 'package:dio/dio.dart';
class CustomInterceptor extends Interceptor {
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
print("onRequest");
return super.onRequest(options, handler);
}
@override
Future onResponse(Response response, ResponseInterceptorHandler handler) {
print("onResponse");
return null;
}
@override
Future onError(DioError err, ErrorInterceptorHandler handler) async {
print("onError: ${err.response.statusCode}");
return handler.next(err); // <--- THE TIP IS HERE
}
}
答案 1 :(得分:3)
var response = await dio.delete(
url,
data: postData,
options: Options(
followRedirects: false,
validateStatus: (status) {
return status < 500;
},
headers: headers,
),
);
请使用兄弟下面的代码,
在代码中添加followRedirects,validateStatus。
答案 2 :(得分:1)
删除'on DioError'-不幸的是,Dio无法处理也不会捕获一些错误(404、500s ...)-我的应用中也有类似的问题。 然后将代码更改为下面发布的代码,或使用其他逻辑“全部捕获”;)
} catch (e) {
if (e is DioError) {
//handle DioError here by error type or by error code
} else {
...
}
//return empty list (you can also return custom error to be handled by Future Builder)
}
您应该正确处理Future Builder状态:snapshot.hasData
,空数据和snapshot.hasError
,以防止将来崩溃
答案 3 :(得分:1)
我也有类似的类型问题。
首先,尝试使用flutter run
从命令提示符运行项目,看看是否出现任何问题。
如果命令提示符未显示任何问题并且您的应用程序运行平稳,则必须检查IDE。如果您使用的是VSCode,则切换到“调试是侧边栏”,请参阅“断点”部分中选中的选项。如果选中All Exceptions
,则调试器将在每个异常时暂停。取消选中All Exceptions
和Uncaught Exceptions
,然后尝试重新启动。
希望这可以解决您的问题。
答案 4 :(得分:0)
此网址字符串模式为${Urls.BASE_API_URL}/mahasiswa/get/id/$id
您不能使用。运算符,并从“”内的任何对象访问内部值。您可以将确切的url存储在其他变量中,并在该行中使用它。代码应如下。
Future<List<Mosque>> getMahasiswaById(String id) async{
try {
var baseURL = Urls.BASE_API_URL;
var apiRespon = await dio.get('${baseURL}/mahasiswa/get/id/$id');
var apiResponJson = apiRespon.data;
print(apiResponJson);
return (apiResponJson['data'] as List).map((p)=>Mosque.fromJson(p)).toList();
}on DioError catch (e) { <<<<< IN THIS LINE
if(e.response.statusCode == 404){
print(e.response.statusCode);
}else{
print(e.message);
print(e.request);
}
}
}
答案 5 :(得分:0)
您可以使用 DioClient
管理超时异常:
有两种方法,声明自定义的 Option
然后分配给 Dio
或直接在 option
下面分配给它,但我更喜欢将这些类型的 Option
分开导向的需要。
可以设置条件获取除400(成功)响应以外的所有问题,但是要注意Connection Timeout,所以这里集成了一个Dio方式:
class YourRepositary {
Dio dioClient;
YourRepositary() {
if (dioClient == null) {
BaseOptions options = new BaseOptions(
baseUrl: "YOUR_APIs_BASE_URL",
receiveDataWhenStatusError: true,
connectTimeout: 30000, // 30 seconds
receiveTimeout: 30000 // 30 seconds
);
dioClient = new Dio(options);
}
}
Future<ProductResponseModel> getProduct(var productRequestInputDto) async {
try {
Response response = await dio.post("/api/getProduct", data: productRequestInputDto);
final ProductResponseModel _productModel = ProductResponseModel.fromJson(response.data);
return _productModel ;
} on DioError catch (ex) {
if(ex.type == DioErrorType.CONNECT_TIMEOUT){
throw Exception("Connection Timeout Exception");
}
throw Exception(ex.message);
}
}
}
最后,下面的示例演示了您如何处理超时异常,甚至是如何处理 API 调用中的后端 500 错误:
void getProduct(){
ProductRequestInputDto productRequest = new ProductRequestInputDto(productId: "666");
var requestBody = jsonEncode(loginRequest);
debugPrint("Request Data : $requestBody");
_apiRepositary.getProduct(requestBody).then((response){
debugPrint("Login Success $response");
//manage your response here
},
onError: (exception){
//Handle exception message
if(exception.message != null ){
debugPrint(exception.message); // Here you get : "Connection Timeout Exception" or even handled 500 errors on your backend.
}
},
);
}
总而言之,这完全是关于 receiveDataWhenStatusError: true
,在 Dio 的选项中。
答案 6 :(得分:0)
dynamic _decodeErrorResponse(dynamic e) {
dynamic data = {"statusCode": -1, "message": "Unknown Error"};
if (e is DioError) {
if (e.type == DioErrorType.response) {
final response = e.response;
try {
if (response != null && response.data != null) {
final Map responseData =
json.decode(response.data as String) as Map;
data["message"] = responseData['message'] as String;
data["statusCode"] = response.statusCode;
}
} catch (e) {
data["message"] = "Internal Error Catch";
}
} else if (e.type == DioErrorType.connectTimeout ||
e.type == DioErrorType.receiveTimeout ||
e.type == DioErrorType.sendTimeout) {
data["message"] = "Request timeout";
data["statusCode"] = 408;
} else if (e.error is SocketException) {
data["message"] = "No Internet Connection!";
}
}
return data;
}
答案 7 :(得分:0)
找到了解决办法。这段代码对我有用。
try {
Dio dio = Dio();
var res = await dio.download(
url + 'fg',
savePath.path + "/filename.bin",
onReceiveProgress: (count, total) {
progress(count, total);
},
);
} on DioError catch (e) {
if (e.type == DioErrorType.response) {
print('catched');
return;
}
if (e.type == DioErrorType.connectTimeout) {
print('check your connection');
return;
}
if (e.type == DioErrorType.receiveTimeout) {
print('unable to connect to the server');
return;
}
if (e.type == DioErrorType.other) {
print('Something went wrong');
return;
}
print(e);
} catch (e) {
print(e);
}
答案 8 :(得分:0)
所选答案运行良好。但是如果有人在添加这些行后仍然收到错误。你可以试试这个。
向字段添加内容类型。
dio.FormData formData = dio.FormData.fromMap({
"file": await dio.MultipartFile.fromFile(
file.path,
filename: fileName,
contentType: MediaType('audio', 'mp4'),
),