Skip to content

Commit

Permalink
Use execute instead of async enqueue OkHttp API on O.
Browse files Browse the repository at this point in the history
Works around a ClassCastException in OkHttp on O due to a framework bug.

Fixes #2355
  • Loading branch information
sjudd committed Sep 8, 2017
1 parent d482b8e commit a4af922
Showing 1 changed file with 40 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.bumptech.glide.integration.okhttp3;

import android.os.Build;
import android.support.annotation.NonNull;
import android.util.Log;
import com.bumptech.glide.Priority;
Expand All @@ -20,13 +21,15 @@
/**
* Fetches an {@link InputStream} using the okhttp library.
*/
public class OkHttpStreamFetcher implements DataFetcher<InputStream> {
public class OkHttpStreamFetcher implements DataFetcher<InputStream>,
okhttp3.Callback {
private static final String TAG = "OkHttpFetcher";
private final Call.Factory client;
private final GlideUrl url;
@Synthetic InputStream stream;
@Synthetic ResponseBody responseBody;
private volatile Call call;
private DataCallback<? super InputStream> callback;

public OkHttpStreamFetcher(Call.Factory client, GlideUrl url) {
this.client = client;
Expand All @@ -41,29 +44,45 @@ public void loadData(Priority priority, final DataCallback<? super InputStream>
requestBuilder.addHeader(key, headerEntry.getValue());
}
Request request = requestBuilder.build();
this.callback = callback;

call = client.newCall(request);
call.enqueue(new okhttp3.Callback() {
@Override
public void onFailure(Call call, IOException e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "OkHttp failed to obtain result", e);
}
callback.onLoadFailed(e);
if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O) {
call.enqueue(this);
} else {
try {
// Calling execute instead of enqueue is a workaround for #2355, where okhttp throws a
// ClassCastException on O.
onResponse(call, call.execute());
} catch (IOException e) {
onFailure(call, e);
} catch (ClassCastException e) {
// It's not clear that this catch is necessary, the error may only occur even on O if
// enqueue is used.
onFailure(call, new IOException("Workaround for framework bug on O", e));
}
}
}

@Override
public void onResponse(Call call, Response response) throws IOException {
responseBody = response.body();
if (response.isSuccessful()) {
long contentLength = responseBody.contentLength();
stream = ContentLengthInputStream.obtain(responseBody.byteStream(), contentLength);
callback.onDataReady(stream);
} else {
callback.onLoadFailed(new HttpException(response.message(), response.code()));
}
}
});
@Override
public void onFailure(Call call, IOException e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "OkHttp failed to obtain result", e);
}

callback.onLoadFailed(e);
}

@Override
public void onResponse(Call call, Response response) throws IOException {
responseBody = response.body();
if (response.isSuccessful()) {
long contentLength = responseBody.contentLength();
stream = ContentLengthInputStream.obtain(responseBody.byteStream(), contentLength);
callback.onDataReady(stream);
} else {
callback.onLoadFailed(new HttpException(response.message(), response.code()));
}
}

@Override
Expand All @@ -78,6 +97,7 @@ public void cleanup() {
if (responseBody != null) {
responseBody.close();
}
callback = null;
}

@Override
Expand Down

0 comments on commit a4af922

Please sign in to comment.