我正在开发Android应用程序,当我试图访问我的API时,我遇到了一个奇怪的错误。我在AsyncTask对象中使用了okhttp执行方法,并且我通过自定义界面将消息检索到UI。对于第一个请求,解决方案就像一个魅力,但当我试图执行第二个时,应用程序死了,出现以下错误:
引起:java.lang.IllegalStateException:已关闭
at okhttp3.internal.http.Http1xStream $ ChunkedSource.read(Http1xStream.java:418)
当我从OKHTTP文档中读出它时,如果我试图两次调用responseBody.string(),则会出现此错误。 (Link to documentation)
老实说我不知道根本原因是什么,因为我只在asyctask中调用body()。string()一次,并且我在每次点击都创建一个新的Request实例。从我的角度来看,一个Request实例等于一个处理(和缓冲区关闭),如果我创建另一个请求,那么它应该从开始,另一个响应对象和另一个响应体开始。
请您查看我的代码,找出问题所在?
这是我的AsyncTask的受影响部分:
@Override
protected String doInBackground(Request... params) {
Request req = params[0];
try {
Response resp = httpClient.newCall(req).execute();
return resp.body().string();
} catch (IOException e) {
Log.e(TAG, "IOException occured :" + e.getMessage());
}finally {
}
return null;
}
@Override
protected void onProgressUpdate(String... values) {
}
@Override
protected void onPostExecute(String response) {
if(response != null){
callback.onResponseReceived(response);
}else{
callback.onConnectionError(new NullPointerException("Empty response after requesting data from medev.hu!"));
}
}
这就是我从UI线程调用的内容:
private void ContentProvRequest(String operation, String params, CredentialsProvider credentialsProvider, HTTPResponseListener callback){
Request request = new Request.Builder().
url(ContentProviderURL + "?operation=" + operation + "¶ms=" + params).
addHeader("Cache-control", "no-cache").
addHeader("Authorization", "Bearer " + getJWT()).
addHeader("Accept-Encoding", "UTF-8").
get().
build();
loginInterceptor.setCredentialsProvider(credentialsProvider);
APIRequest apiRequest = new APIRequest(httpClient,callback,securePreferences);
apiRequest.execute(request);
}
这是httpclient配置:
public RemoteDBAdapter(MainActivity activity) {
this.mActivity = activity;
securePreferences= activity.getSecurePref();
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.cipherSuites(
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
)
.build();
loginInterceptor = new LoginInterceptor(securePreferences);
httpClient = new OkHttpClient.Builder()
.followRedirects(true)
.addInterceptor(loginInterceptor)
.connectionSpecs(Collections.singletonList(spec))
.build();
}
LoginInterceptor.java:
public class LoginInterceptor implements Interceptor {
public static String TAG = "HTTPInterceptor";
private Chain mChain;
private SharedPreferences securePreferences;
private CredentialsProvider credentialsProvider;
public LoginInterceptor(SharedPreferences sharedPreferences) {
this.securePreferences = sharedPreferences;
}
public void setCredentialsProvider(CredentialsProvider credentialsProvider){
this.credentialsProvider = credentialsProvider;
}
@Override
public Response intercept(Chain chain) throws IOException {
this.mChain = chain;
Request origRequest = chain.request();
Response origResponse = chain.proceed(origRequest);
if(origResponse.code() == 401){
RemoteDBAdapter.setJWT(getToken());
Log.i(TAG, "New TOKEN : " + RemoteDBAdapter.getJWT());
Request newRequest = new Request.Builder().
url(origRequest.url()).
addHeader("Cache-control", "no-cache").
addHeader("Authorization", "Bearer " + RemoteDBAdapter.getJWT()).
addHeader("Accept-Encoding", "UTF-8").
build();
Response newResponse = chain.proceed(newRequest);
return newResponse;
}else{
Log.i(TAG, "Token is still valid. Refresh skipped. " + origResponse.body().string());
return origResponse;
}
}
private String getToken(){
Log.i(TAG, "Requesting new Token...");
String usrname;
String passwd;
if(credentialsProvider != null){
usrname = credentialsProvider.getUserName();
passwd = credentialsProvider.getPassword();
}else{
usrname = securePreferences.getString(MainActivity.KEY_USERNAME,"None");
passwd = securePreferences.getString(MainActivity.KEY_PASSWD,"None");
}
RequestBody body = new FormBody.Builder().
add("useremail", usrname.replace("/", "@")).
add("password", passwd).
build();
Request tokenRequest = new Request.Builder().
url(RemoteDBAdapter.TokenProviderURL).
addHeader("Cache-control", "no-cache").
addHeader("Content-Type", "application/x-www-form-urlencoded").
addHeader("Accept-Encoding", "UTF-8").
cacheControl(CacheControl.FORCE_NETWORK).
post(body).
build();
Response tokenResponse = null;
String jwtString = "";
try {
tokenResponse = mChain.proceed(tokenRequest);
String jsonString = tokenResponse.body().string();
Log.i(TAG, "Response from the server: (" + tokenResponse.code() + ") " + jsonString);
JSONObject responseInJSON = new JSONObject(jsonString);
Log.i(TAG, "Token refreshed!");
jwtString = responseInJSON.getString("jwt");
} catch (IOException e) {
Log.e(TAG, "IOException: " + e.getMessage());
} catch (JSONException e) {
Log.e(TAG, "JSONException: " + e.getMessage());
} catch (NullPointerException e){
Log.e(TAG, "NullPointerException: " + e.getMessage());
}
return jwtString;
}
}
完整的堆栈跟踪:
FATAL EXCEPTION: AsyncTask #3
Process: hu.medev.projects.myapplication, PID: 11094
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.IllegalStateException: closed
at okhttp3.internal.http.Http1xStream$ChunkedSource.read(Http1xStream.java:418)
at okio.Buffer.writeAll(Buffer.java:993)
at okio.RealBufferedSource.readByteArray(RealBufferedSource.java:106)
at okhttp3.ResponseBody.bytes(ResponseBody.java:128)
at okhttp3.ResponseBody.string(ResponseBody.java:154)
at hu.medev.projects.android.medev_bodybuilding.DB.Remote.APIRequest.doInBackground(APIRequest.java:39)
at hu.medev.projects.android.medev_bodybuilding.DB.Remote.APIRequest.doInBackground(APIRequest.java:15)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
提前致谢, Tangomajom