Skip to content

Commit a4af922

Browse files
committed
Use execute instead of async enqueue OkHttp API on O.
Works around a ClassCastException in OkHttp on O due to a framework bug. Fixes bumptech#2355
1 parent d482b8e commit a4af922

File tree

1 file changed

+40
-20
lines changed

1 file changed

+40
-20
lines changed

integration/okhttp3/src/main/java/com/bumptech/glide/integration/okhttp3/OkHttpStreamFetcher.java

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.bumptech.glide.integration.okhttp3;
22

3+
import android.os.Build;
34
import android.support.annotation.NonNull;
45
import android.util.Log;
56
import com.bumptech.glide.Priority;
@@ -20,13 +21,15 @@
2021
/**
2122
* Fetches an {@link InputStream} using the okhttp library.
2223
*/
23-
public class OkHttpStreamFetcher implements DataFetcher<InputStream> {
24+
public class OkHttpStreamFetcher implements DataFetcher<InputStream>,
25+
okhttp3.Callback {
2426
private static final String TAG = "OkHttpFetcher";
2527
private final Call.Factory client;
2628
private final GlideUrl url;
2729
@Synthetic InputStream stream;
2830
@Synthetic ResponseBody responseBody;
2931
private volatile Call call;
32+
private DataCallback<? super InputStream> callback;
3033

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

4549
call = client.newCall(request);
46-
call.enqueue(new okhttp3.Callback() {
47-
@Override
48-
public void onFailure(Call call, IOException e) {
49-
if (Log.isLoggable(TAG, Log.DEBUG)) {
50-
Log.d(TAG, "OkHttp failed to obtain result", e);
51-
}
52-
callback.onLoadFailed(e);
50+
if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O) {
51+
call.enqueue(this);
52+
} else {
53+
try {
54+
// Calling execute instead of enqueue is a workaround for #2355, where okhttp throws a
55+
// ClassCastException on O.
56+
onResponse(call, call.execute());
57+
} catch (IOException e) {
58+
onFailure(call, e);
59+
} catch (ClassCastException e) {
60+
// It's not clear that this catch is necessary, the error may only occur even on O if
61+
// enqueue is used.
62+
onFailure(call, new IOException("Workaround for framework bug on O", e));
5363
}
64+
}
65+
}
5466

55-
@Override
56-
public void onResponse(Call call, Response response) throws IOException {
57-
responseBody = response.body();
58-
if (response.isSuccessful()) {
59-
long contentLength = responseBody.contentLength();
60-
stream = ContentLengthInputStream.obtain(responseBody.byteStream(), contentLength);
61-
callback.onDataReady(stream);
62-
} else {
63-
callback.onLoadFailed(new HttpException(response.message(), response.code()));
64-
}
65-
}
66-
});
67+
@Override
68+
public void onFailure(Call call, IOException e) {
69+
if (Log.isLoggable(TAG, Log.DEBUG)) {
70+
Log.d(TAG, "OkHttp failed to obtain result", e);
71+
}
72+
73+
callback.onLoadFailed(e);
74+
}
75+
76+
@Override
77+
public void onResponse(Call call, Response response) throws IOException {
78+
responseBody = response.body();
79+
if (response.isSuccessful()) {
80+
long contentLength = responseBody.contentLength();
81+
stream = ContentLengthInputStream.obtain(responseBody.byteStream(), contentLength);
82+
callback.onDataReady(stream);
83+
} else {
84+
callback.onLoadFailed(new HttpException(response.message(), response.code()));
85+
}
6786
}
6887

6988
@Override
@@ -78,6 +97,7 @@ public void cleanup() {
7897
if (responseBody != null) {
7998
responseBody.close();
8099
}
100+
callback = null;
81101
}
82102

83103
@Override

0 commit comments

Comments
 (0)