使用Volley HTTP库在Android活动中考虑此代码。 HTTP请求永远不会完成。它既不接收正常响应也不接收错误响应。但是如果注释掉while (!done)
块,那么一切都会正常完成。这让我感到惊讶,因为Volley我正在制作一个RequestQueue
,其中包含一个线程池,其中使用完全独立的线程来执行HTTP请求。那么为什么如果这个线程正在睡眠,请求永远不会完成?
代码:
package com.adobe.instore.activities;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import com.adobe.instore.R;
import com.adobe.instore.Urls;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONObject;
public class VolleyTestActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_volley_test);
}
private static boolean done = false;
protected void makeRequest(View v) {
Log.i(getLocalClassName(), "Request");
RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
queue.start();
queue.add(new JsonObjectRequest(Request.Method.GET, Urls.STATIC_URL + "/profiles.json", null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.i(getLocalClassName(), "Response");
done = true;
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(getLocalClassName(), "Error");
}
}));
Log.i(getLocalClassName(), "Awaiting completion");
while(!done) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.i(getLocalClassName(), "Done");
}
}
答案 0 :(得分:1)
在UI线程上调用Volley onResponse和onErrorResponse。因此,如果您的主线程处于休眠状态,则不会调用onResponse和onErrorResponse
答案 1 :(得分:1)
视图在主线程中呈现(有时称为UI线程)。您创建的循环会阻止渲染以及后面的其他代码。从技术上讲,在这个线程中调用Thread.sleep(...);
是一个坏主意,因为很多事情都会受到影响。 Volley是一个http库,旨在通过不需要显式调用自己的Thread来简化您的生活。
在Volley中,所有网络和缓存调度都在一个单独的线程(引擎盖后)完成,同时响应被发送回主线程。这只意味着onResponse
和onError
发生在主线程中。
为了让它更简单,你可以这样做:
public class VolleyTestActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_volley_test);
}
public void makeRequest(View v) {
Log.i(getLocalClassName(), "Request");
RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
queue.start();
queue.add(new JsonObjectRequest(Request.Method.GET, Urls.STATIC_URL + "/profiles.json", null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.i(getLocalClassName(), "Response");
Log.i(getLocalClassName(), "Done");
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(getLocalClassName(), "Error");
}
}));
Log.i(getLocalClassName(), "Awaiting completion");
}
}
此外,while()
和Thread.sleep
使线程保持忙碌状态。因此,在主线程中排队的任何执行都无法访问,直到循环完成(但它不会发生)。您可能会认为onResponse
可以绕过无限循环?答案是不;因为onResponse
由主线程而不是后台线程排队。为了说明,请参见下图:
图1:Android Volley内部架构(图片来自文档)
如果您看到在主线程上传递的解析响应的框,其颜色为BLUE,则表示它是调用它的主线程(简化它意味着onResponse
和{{ 1}}由主线程调用)除非它是橙色或绿色,否则循环将被你的布尔值绕过。