okhttp3 使用 glide 异步加载图片时抛出 NetworkOnMainThreadException
okhttp3 throws NetworkOnMainThreadException when loading images asynchronously with glide
我正在尝试像这样将图像异步加载到 Leanback 中的 CardPresenter。
public interface CustomImageModel {
String requestCustomUrl(int width, int height);
}
public static class CustomImageModelGrabber implements CustomImageModel {
public CustomImageModelGrabber() {
}
@Override
public String requestCustomUrl(int width, int height) {
OkHttpClient client = new OkHttpClient;
Request request = new Request.Builder().url(image_url).build();
return client.newCall(request).execute().body().string();
}
}
public static class CustomImageUrlLoader extends BaseGlideUrlLoader<CustomImageModel> {
public CustomImageUrlLoader(Context context) {
super( context );
}
@Override
protected String getUrl(CustomImageModel model, int width, int height) {
return model.requestCustomUrl();
}
}
在CardPresenter.java
@Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
CustomImageModel customImageRequest = new CustomImageModelGrabber();
Glide
.with( context )
.using( new CustomImageUrlLoader( context ) )
.load( customImageRequest )
.into( imageView1 );
}
不幸的是,这没有按预期工作。 只有少数图片被正确加载到卡片展示器中,但大部分都没有,并抛出以下错误:
android.os.NetworkOnMainThreadException
android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
哪些有效哪些无效完全是随机的。
我也试过在MainActivity.java中设置严格模式。
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
虽然此解决方案可以正确加载所有图像并且不会引发任何 NetworkOnMainThreadException
错误,但它会带来巨大的性能问题。滚动变得缓慢和滞后,显示以下消息:
I/Choreographer: Skipped 182 frames! The application may be doing too much work on its main thread.
有什么解决方案可以让图片异步加载,同时保持流畅和良好的性能吗?
我的做法是完全错误的。我以为 BaseGlideUrlLoader
在后台线程上运行,但事实并非如此。
所以要执行的代码如下:
@Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
final ImageCardView cardView = (ImageCardView) viewHolder.view;
OkHttpClient client = new OkHttpClient;
Request request = new Request.Builder().url(image_url).build();
client.newCall(request).enqueue(new Callback() {
@Override public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override public void onResponse(Call call, Response response) throws IOException {
try (ResponseBody responseBody = response.body()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
String imageFromResponse = responseBody.string();
// do whatever is needed to get the image (i.e JSON-handling)
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = new Runnable() {
@Override
public void run() {
Glide.with(cardView.getContext())
.load(imagefromResponse)
.error(mDefaultCardImage)
.into(cardView.getMainImageView());
}
};
}
});
}
我正在尝试像这样将图像异步加载到 Leanback 中的 CardPresenter。
public interface CustomImageModel {
String requestCustomUrl(int width, int height);
}
public static class CustomImageModelGrabber implements CustomImageModel {
public CustomImageModelGrabber() {
}
@Override
public String requestCustomUrl(int width, int height) {
OkHttpClient client = new OkHttpClient;
Request request = new Request.Builder().url(image_url).build();
return client.newCall(request).execute().body().string();
}
}
public static class CustomImageUrlLoader extends BaseGlideUrlLoader<CustomImageModel> {
public CustomImageUrlLoader(Context context) {
super( context );
}
@Override
protected String getUrl(CustomImageModel model, int width, int height) {
return model.requestCustomUrl();
}
}
在CardPresenter.java
@Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
CustomImageModel customImageRequest = new CustomImageModelGrabber();
Glide
.with( context )
.using( new CustomImageUrlLoader( context ) )
.load( customImageRequest )
.into( imageView1 );
}
不幸的是,这没有按预期工作。 只有少数图片被正确加载到卡片展示器中,但大部分都没有,并抛出以下错误:
android.os.NetworkOnMainThreadException
android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
哪些有效哪些无效完全是随机的。
我也试过在MainActivity.java中设置严格模式。
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
虽然此解决方案可以正确加载所有图像并且不会引发任何 NetworkOnMainThreadException
错误,但它会带来巨大的性能问题。滚动变得缓慢和滞后,显示以下消息:
I/Choreographer: Skipped 182 frames! The application may be doing too much work on its main thread.
有什么解决方案可以让图片异步加载,同时保持流畅和良好的性能吗?
我的做法是完全错误的。我以为 BaseGlideUrlLoader
在后台线程上运行,但事实并非如此。
所以要执行的代码如下:
@Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
final ImageCardView cardView = (ImageCardView) viewHolder.view;
OkHttpClient client = new OkHttpClient;
Request request = new Request.Builder().url(image_url).build();
client.newCall(request).enqueue(new Callback() {
@Override public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override public void onResponse(Call call, Response response) throws IOException {
try (ResponseBody responseBody = response.body()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
String imageFromResponse = responseBody.string();
// do whatever is needed to get the image (i.e JSON-handling)
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = new Runnable() {
@Override
public void run() {
Glide.with(cardView.getContext())
.load(imagefromResponse)
.error(mDefaultCardImage)
.into(cardView.getMainImageView());
}
};
}
});
}