The question is published on by Tutorial Guruji team.
I’m trying to load images asynchronously into a CardPresenter in Leanback like this.
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(); } }
In 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 ); }
Unfortunately this doesn’t work as expected. Only a few images are loaded correctly into the card presenter, but most of them are not, and the following error is thrown:
android.os.NetworkOnMainThreadException android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
It’s totally random which work and which don’t.
I also tried setting the strict mode in MainActivity.java.
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy);
While this solution loads all images correctly and doesn’t throw any NetworkOnMainThreadException
errors, it comes with huge performance issues. The scrolling becomes slow and laggy, showing me the following message:
I/Choreographer: Skipped 182 frames! The application may be doing too much work on its main thread.
Is there any solution to make the images load asynchronously while still maintaining a smooth and good performance?
Answer
My approach was totally wrong. I thought that BaseGlideUrlLoader
runs on a background-thread, but it doesn’t.
So the code to go is the following:
@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()); } }; } }); }