我正在尝试使用volley来发出异步并行请求。我知道这应该是默认行为,我无法弄清楚我做错了什么。
我编写了一个Instrumentation测试来检查RequestQueue处理的异步性。这应该在de androidTest 文件夹里面,它不会断言任何东西,我只是用它来检查print()输出:
package com.test.testparallelvolley;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
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.HttpHeaderParser;
import com.android.volley.toolbox.JsonRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONException;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
@RunWith(AndroidJUnit4.class)
public class ParallelRequestTest {
private static Context context;
private static RequestQueue mRequestQueue;
public ParallelRequestTest(){
}
@BeforeClass
public static void initilize(){
System.out.println("INITIALIZING");
try {
context = InstrumentationRegistry.getTargetContext();
mRequestQueue = newRequestQueue(context.getApplicationContext());
}catch(Throwable t){
t.printStackTrace();
}
}
@Test
public void testAsync() throws Exception{
addRequest("A");
addRequest("B");
Thread.sleep(15000);
for(String msg : log){
System.out.println(msg);
}
}
private void addRequest(final String desc) throws AuthFailureError {
String url = "https://api.github.com/users/rails/repos";
String body = "";
Response.Listener<JSONArray> success = new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
log(desc + " success ");
// log(response.toString());
if(desc.equals("A")){
try {
log(desc + " sleeping 10s ");
Thread.sleep(10000);
log(desc + " awake ");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log(desc + " finish success listener ");
}
};
Response.ErrorListener error = new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
log(desc + " ERROR " + error.getMessage());
error.printStackTrace();
log(desc + " finish failure listener ");
}
};
JsonRequest<JSONArray> req = new JsonRequest<JSONArray>(Request.Method.GET, url , body, success, error) {
@Override
protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
log(desc + " RESPONSE: " + response.statusCode);
try {
String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(new JSONArray(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
};
mRequestQueue.add(req);
log("ADDED " + desc);
}
public static RequestQueue newRequestQueue(Context context) {
return Volley.newRequestQueue(context);
}
// public static RequestQueue newRequestQueue(Context context) {
// File cacheDir = new File(context.getCacheDir(), "volley");
//
// HttpStack stack = new HurlStack();
//
// ByteArrayPool pool = new ByteArrayPool(65536);
//
// Network network = new BasicNetwork(stack, pool){
// @Override
// public NetworkResponse performRequest(Request<?> request) throws VolleyError {
// log("PERFORMING REQUEST");
// return super.performRequest(request);
// }
// };
//
// RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network, 100);
// queue.start();
//
// return queue;
// }
private static ArrayList<String> log = new ArrayList<>();
private static void log(String message){
log.add(message);
}
}
我试过在模拟器和实际的智能手机上运行它,结果是一样的。 testAsync()方法打印以下输出:
ADDED A
ADDED B
PERFORMING REQUEST
A RESPONSE: 304
A success
{"status":"ok"}
A sleeping 10s
A awake
A finish success listener
PERFORMING REQUEST
B RESPONSE: 304
B success
{"status":"ok"}
B finish success listener
正如您所见,请求正在同步执行。 甚至更奇怪,凌空等待响应侦听器在执行第二个请求之前返回。 我也尝试明确指定网络池的大小和工作线程的数量 - 检查注释的newRequestQueue()函数。
这是build.gradle文件
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
applicationId "com.test.testparallelvolley"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile "com.android.volley:volley:1.0.0"
androidTestCompile 'com.android.support:support-annotations:23.1.1'
androidTestCompile 'com.android.support.test:rules:0.5'
androidTestCompile 'com.android.support.test:runner:0.5'
}
和AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.testparallelvolley">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
</application>
</manifest>
我做错了什么?
答案 0 :(得分:0)
Volley RequestQueue正在主线程上运行。响应侦听器的onError和onSuccess也在主线程上运行。当您在A onSuccess中休眠主线程时,Volley不会恢复其队列