如何从公开的onResponse函数中获取响应?
编辑:我得到了解析错误:“无法为最终变量'res'赋值”
public JSONObject getRestRequest() {
final JSONObject res;
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, this.restPath, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) { // basically I just want to return this response
res = response;
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
}
);
return res;
}
}
答案 0 :(得分:0)
您正在尝试立即获得结果,但是请求是异步的,您可以同步调用请求
synchronized (this) {
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, "", null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) { // basically I just want to return this response
res = response;
YourClassName.this.notify();
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
}
);
this.wait();
}
但是它将锁定您的线程,直到请求完成 我确定您需要异步进行 请阅读有关Java多线程的文档
答案 1 :(得分:0)
由于网络请求是在单独的线程上发生的,因此您不能完全按照您的描述进行操作。
首先,让我们遍历代码,以便清楚发生了什么事情:
public JSONObject getRestRequest() { // 1 - your method is invoked by another method and control starts here
final JSONObject res; // 2 - This final (i.e. immutable) field is created
// 3 - You create a new request object - no networking is happening yet
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, this.restPath, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) { // basically I just want to return this response
// 5 - Some time later, after the request completes, this method is invoked
// BUT - you can't assign to res because it's final (immutable)
res = response;
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
}
);
// 4 - IMMEDIATELY after creating "request", the value that was created in step 2 (which is null) is returned
return res;
}
因此,您尝试同步执行异步操作(启动线程以发出网络请求并解析响应)(阻塞直到完成返回结果)。
那是你的问题。要解决此问题,您有两种选择:
1-使用异步回调:
public void getRestRequest(final Callback<JSONObject> callback) { // 1 - your method is invoked by another method and control starts here
// Now you're passing in a callback that will be invoked later with the result
// final JSONObject res; // 2 - You no longer need this local variable
// 3 - You create a new request object - no networking is happening yet
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, this.restPath, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) { // basically I just want to return this response
// 5 - Some time later, after the request completes, this method is invoked
// This time, you invoke your callback with the result
callback.onSuccess(response)
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
// 6 - You can also pass back errors to your callback
callback.onError(error);
}
}
);
// 4 - You return IMMEDIATELY after creating "request"
}
此方法更为常见。创建回调,将其传递给函数,然后处理响应:
// 1 - Start showing some UI that a request is happening
showProgressDialog();
// 2 - A new callback to handle the network response is created - no request is happening yet
Callback<JSONObject> callback = new Callback<>() {
public void onSuccess(JSONObject response) {
// 4 - Some time later, when the network response finishes, this called
// Handle response
dismissProgressDialog(); // Back on the main thread, so safe to update the UI
}
public void onError(VolleyError error) {
// 5 - Or this is called if the request failed
// Handle error
dismissProgressDialog(); // Back on the main thread, so safe to update the UI
}
}
// 3 - Invoke the network request which will happen in a background thread.
// Meanwhile, the main (UI) thread is not blocked and the progress dialog continues to spin
network.getRestRequest(callback)
选项2-使用RequestFuture。
public JSONObject getRestRequest() { // 1 - your method is invoked by another method and control starts here
// 2 - Initialize a Future to use to synchronously get the result
RequestFuture<JSONObject> future = RequestFuture.newFuture();
// 3 - You create a new request object with the future as the listener - no networking is happening yet
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, this.restPath, future, future);
// 4 - You return the value the future will obtain by making the network request
// THIS IS A BLOCKING CALL SO DON'T DO THIS ON THE MAIN THREAD
// This will also throw an exception if it fails
return future.get();
}
因此,现在您可以得到最初想要的结果:
...
JSONObject response = network.getRestRequest()
...
但是您不能在主(UI)线程上执行此操作(如果尝试在主线程上进行联网,则Android会引发异常。但是,如果您已经在单独的线程上进行工作, ,这很好。
希望有帮助!