处理 Volley 中的错误(有期货)?
Handling errors in Volley (with futures)?
实施我的 LoginActivity.java,我设置了另一个名为 AuthClient
的文件+class
,它大量使用了 Volley。 UserLoginTask
需要从其 doInBackground
return 一个 Boolean
以便远程调用登录 succeeds/fails.
所以按照 Can I do a synchronous request with volley?,我设置:
void login(final HashMap<String, String> data,
Response.Listener<JSONObject> listener,
Response.ErrorListener errorListener) {
JsonObjectRequest req = new JsonObjectRequest(
api_prefix + "/auth", new JSONObject(data), listener, errorListener
);
queue.add(req); // RequestQueue
}
boolean loginResponseHandler(RequestFuture<VolleyError> err_future,
RequestFuture<JSONObject> future) {
try {
VolleyError err_response = err_future.get();
JSONObject response = future.get();
System.out.println("response.toString() = " + response.toString());
return true;
} catch (InterruptedException | ExecutionException e) {
System.err.println("e = " + e.toString());
return false;
} catch (Exception e) { // Even tried this!
System.err.println("Exception::e = " + e.toString());
throw e;
}
}
@Override
protected Boolean doInBackground(Void... params) {
RequestFuture<JSONObject> future = RequestFuture.newFuture();
RequestFuture<VolleyError> err_future = RequestFuture.newFuture();
login(/*omitted for brevity*/, err_future, future);
return loginResponseHandler(err_future, future);
} // Actual code has login/loginResponseHandler in separate class+file, and more^
但是查看调试日志,我得到了错误(来自其他地方,而不是我正在调试的地方):
08-24 23:17:13.228 7255-7288 E/Volley: [177] BasicNetwork.performRequest: Unexpected response code 400 for http://192.168.5.3:3003/v1/api/auth
我打算如何处理错误? - 还有参考脚手架吗?
啊,这很愚蠢,这是解决方案:
if (err_future != null) throw err_future.get();
在 loginResponseHandler
中的 try
之后添加,替换:
VolleyError err_response = err_future.get();
现在错误被抛出并被捕获,因此可以通过编程方式处理。
编辑:如何获得实际的网络响应? - 像状态代码和错误主体?喜欢:com.android.volley.NetworkResponse
首先
VolleyError err_response = err_future.get();
如果请求没有错误你会得到一些转换异常是不好的。
实际上您不需要 2 个 Futures,因为 RequestFuture 实现了 Response 和 Error Listeners。
说到点子上。
future.get()
returns 结果。如果发生错误,则它会抛出执行异常,该异常可能包含 VolleyError 异常,如果收到任何网络数据,该异常可能包含一些网络数据。
您需要做的就是将内部异常转换为 VolleyError 并在您的 catch 语句中获取数据。
try {
JSONObject response = future.get();
System.out.println("response.toString() = " + response.toString());
return true;
} catch (InterruptedException | ExecutionException e) {
if (VolleyError.class.isAssignableFrom(e.getCause().getClass())) {
VolleyError ve = (VolleyError) e.getCause();
System.err.println("ve = " + ve.toString());
if (ve.networkResponse != null) {
System.err.println("ve.networkResponse = " +
ve.networkResponse.toString());
System.err.println("ve.networkResponse.statusCode = " +
ve.networkResponse.statusCode);
System.err.println("ve.networkResponse.data = " +
new String(ve.networkResponse.data));
return false;
}
}
}
更新
关于 'the best client design' 这取决于您所做的应用程序设计选择。但是,您必须了解一些关于错误的重要信息:
错误可以分为 3 种主要类型:protocol/network 有网络响应或没有网络响应的错误以及其他纯粹 java 且与处理相关的错误 request/response,其中最常见的是解析数据。
有 2 种主要方法可以处理不是来自您的代码的错误。
- 使用自定义重试策略
- 将错误通知用户
通常情况下,您可能会使用第一个来处理某些网络错误和 5xx 错误,然后使用一些消息处理程序来让用户知道发生了什么。
同样,如何实现它实际上取决于您的应用架构。我个人经常使用 rxJava 并应用某种数据流设计,我将所有错误集中在一个地方,然后根据请求、错误本身和应用程序状态决定如何处理它们。
对于我的应用程序,我使用 jus(highly extended volley) with rx-jus module and RxQueueHub class based on rxHub,所以我可以在一个地方获得所有处理程序可用的所有响应和错误。
实施我的 LoginActivity.java,我设置了另一个名为 AuthClient
的文件+class
,它大量使用了 Volley。 UserLoginTask
需要从其 doInBackground
return 一个 Boolean
以便远程调用登录 succeeds/fails.
所以按照 Can I do a synchronous request with volley?,我设置:
void login(final HashMap<String, String> data,
Response.Listener<JSONObject> listener,
Response.ErrorListener errorListener) {
JsonObjectRequest req = new JsonObjectRequest(
api_prefix + "/auth", new JSONObject(data), listener, errorListener
);
queue.add(req); // RequestQueue
}
boolean loginResponseHandler(RequestFuture<VolleyError> err_future,
RequestFuture<JSONObject> future) {
try {
VolleyError err_response = err_future.get();
JSONObject response = future.get();
System.out.println("response.toString() = " + response.toString());
return true;
} catch (InterruptedException | ExecutionException e) {
System.err.println("e = " + e.toString());
return false;
} catch (Exception e) { // Even tried this!
System.err.println("Exception::e = " + e.toString());
throw e;
}
}
@Override
protected Boolean doInBackground(Void... params) {
RequestFuture<JSONObject> future = RequestFuture.newFuture();
RequestFuture<VolleyError> err_future = RequestFuture.newFuture();
login(/*omitted for brevity*/, err_future, future);
return loginResponseHandler(err_future, future);
} // Actual code has login/loginResponseHandler in separate class+file, and more^
但是查看调试日志,我得到了错误(来自其他地方,而不是我正在调试的地方):
08-24 23:17:13.228 7255-7288 E/Volley: [177] BasicNetwork.performRequest: Unexpected response code 400 for http://192.168.5.3:3003/v1/api/auth
我打算如何处理错误? - 还有参考脚手架吗?
啊,这很愚蠢,这是解决方案:
if (err_future != null) throw err_future.get();
在 loginResponseHandler
中的 try
之后添加,替换:
VolleyError err_response = err_future.get();
现在错误被抛出并被捕获,因此可以通过编程方式处理。
编辑:如何获得实际的网络响应? - 像状态代码和错误主体?喜欢:com.android.volley.NetworkResponse
首先
VolleyError err_response = err_future.get();
如果请求没有错误你会得到一些转换异常是不好的。
实际上您不需要 2 个 Futures,因为 RequestFuture 实现了 Response 和 Error Listeners。
说到点子上。
future.get()
returns 结果。如果发生错误,则它会抛出执行异常,该异常可能包含 VolleyError 异常,如果收到任何网络数据,该异常可能包含一些网络数据。 您需要做的就是将内部异常转换为 VolleyError 并在您的 catch 语句中获取数据。
try {
JSONObject response = future.get();
System.out.println("response.toString() = " + response.toString());
return true;
} catch (InterruptedException | ExecutionException e) {
if (VolleyError.class.isAssignableFrom(e.getCause().getClass())) {
VolleyError ve = (VolleyError) e.getCause();
System.err.println("ve = " + ve.toString());
if (ve.networkResponse != null) {
System.err.println("ve.networkResponse = " +
ve.networkResponse.toString());
System.err.println("ve.networkResponse.statusCode = " +
ve.networkResponse.statusCode);
System.err.println("ve.networkResponse.data = " +
new String(ve.networkResponse.data));
return false;
}
}
}
更新
关于 'the best client design' 这取决于您所做的应用程序设计选择。但是,您必须了解一些关于错误的重要信息:
错误可以分为 3 种主要类型:protocol/network 有网络响应或没有网络响应的错误以及其他纯粹 java 且与处理相关的错误 request/response,其中最常见的是解析数据。
有 2 种主要方法可以处理不是来自您的代码的错误。
- 使用自定义重试策略
- 将错误通知用户
通常情况下,您可能会使用第一个来处理某些网络错误和 5xx 错误,然后使用一些消息处理程序来让用户知道发生了什么。
同样,如何实现它实际上取决于您的应用架构。我个人经常使用 rxJava 并应用某种数据流设计,我将所有错误集中在一个地方,然后根据请求、错误本身和应用程序状态决定如何处理它们。
对于我的应用程序,我使用 jus(highly extended volley) with rx-jus module and RxQueueHub class based on rxHub,所以我可以在一个地方获得所有处理程序可用的所有响应和错误。