The image is not loaded on the Glide version 4.9.0 while working well on glide 4.8.0.
Image is loaded on some places, but for one of our widget the image failed to load. I have added below the widget example and the stack trace from the error.
This is because we update UI component on background thread, the only workaround is making all ui change inside OnResourceReady to run in UI thread. Do you know any better ways to do this ?
Let me know if you need additional information.
Glide Version: 4.9.0
Integration libraries: using glide transformer library version 3.3.0
Device/Android Version: Android version 8 and 6, Asus & samsung all catching error.
Code example where error happen:
Glide.with(mContext)
.load(mImageUrl[position])
.apply(new RequestOptions().onlyRetrieveFromCache(true))
.transition(DrawableTransitionOptions.withCrossFade())
.error(Glide.with(mContext).load(mImageUrl[position]).listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
ImageWidget.setNormal();
TouchImageView.setImageDrawable(resource);
TouchImageView.setVisibility(View.VISIBLE);
width[position] = resource.getIntrinsicWidth();
height[position] = resource.getIntrinsicHeight();
return false;
}
})).listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
ImageWidget.setNormal();
TouchImageView.setImageDrawable(resource);
TouchImageView.setVisibility(View.VISIBLE);
width[position] = resource.getIntrinsicWidth();
height[position] = resource.getIntrinsicHeight();
return false;
}
}).submit();
Stack trace / LogCat:
E/GlideExecutor: Request threw uncaught throwable
com.bumptech.glide.load.engine.CallbackException: Unexpected exception thrown by non-Glide code
at com.bumptech.glide.load.engine.EngineJob.callCallbackOnResourceReady(EngineJob.java:154)
at com.bumptech.glide.load.engine.EngineJob$CallResourceReady.run(EngineJob.java:398)
at com.bumptech.glide.util.Executors$2.execute(Executors.java:30)
at com.bumptech.glide.load.engine.EngineJob.notifyCallbacksOfResult(EngineJob.java:250)
at com.bumptech.glide.load.engine.EngineJob.onResourceReady(EngineJob.java:304)
at com.bumptech.glide.load.engine.DecodeJob.notifyComplete(DecodeJob.java:336)
at com.bumptech.glide.load.engine.DecodeJob.notifyEncodeAndRelease(DecodeJob.java:442)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromRetrievedData(DecodeJob.java:424)
at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherReady(DecodeJob.java:387)
at com.bumptech.glide.load.engine.DataCacheGenerator.onDataReady(DataCacheGenerator.java:95)
at com.bumptech.glide.load.model.ByteBufferFileLoader$ByteBufferFetcher.loadData(ByteBufferFileLoader.java:74)
at com.bumptech.glide.load.engine.DataCacheGenerator.startNext(DataCacheGenerator.java:75)
at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:309)
at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:276)
at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:235)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:446)
Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7753)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1225)
at android.view.View.requestLayout(View.java:23093)
at android.view.View.requestLayout(View.java:23093)
at android.view.View.requestLayout(View.java:23093)
at android.view.View.requestLayout(View.java:23093)
at android.view.View.requestLayout(View.java:23093)
at android.view.View.requestLayout(View.java:23093)
at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:360)
at android.view.View.requestLayout(View.java:23093)
at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:360)
at android.view.View.requestLayout(View.java:23093)
at android.view.View.requestLayout(View.java:23093)
at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:360)
at android.view.View.requestLayout(View.java:23093)
at android.view.View.setFlags(View.java:14102)
at android.view.View.setVisibility(View.java:9992)
at com.myapp.android.view.widget.LoadingWidget.setNormal(LoadingWidget.java:114)
at com.myapp.android.view.adapter.ImageFullScreenPagerAdapter$1.onResourceReady(ImageFullScreenPagerAdapter.java:128)
at com.myapp.android.view.adapter.ImageFullScreenPagerAdapter$1.onResourceReady(ImageFullScreenPagerAdapter.java:120)
at com.bumptech.glide.request.SingleRequest.onResourceReady(SingleRequest.java:572)
at com.bumptech.glide.request.SingleRequest.onResourceReady(SingleRequest.java:544)
at com.bumptech.glide.load.engine.EngineJob.callCallbackOnResourceReady(EngineJob.java:152)
at com.bumptech.glide.load.engine.EngineJob$CallResourceReady.run(EngineJob.java:398)
at com.bumptech.glide.util.Executors$2.execute(Executors.java:30)
at com.bumptech.glide.load.engine.EngineJob.notifyCallbacksOfResult(EngineJob.java:250)
at com.bumptech.glide.load.engine.EngineJob.onResourceReady(EngineJob.java:304)
at com.bumptech.glide.load.engine.DecodeJob.notifyComplete(DecodeJob.java:336)
at com.bumptech.glide.load.engine.DecodeJob.notifyEncodeAndRelease(DecodeJob.java:442)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromRetrievedData(DecodeJob.java:424)
at com.bumptech.glide.load.engine.DecodeJob.onDataFetcherReady(DecodeJob.java:387)
at com.bumptech.glide.load.engine.DataCacheGenerator.onDataReady(DataCacheGenerator.java:95)
at com.bumptech.glide.load.model.ByteBufferFileLoader$ByteBufferFetcher.loadData(ByteBufferFileLoader.java:74)
at com.bumptech.glide.load.engine.DataCacheGenerator.startNext(DataCacheGenerator.java:75)
at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:309)
at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:276)
at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:235)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:446)
This issue has been automatically marked as stale because it has not had activity in the last seven days. It will be closed if no further activity occurs within the next seven days. Thank you for your contributions.
Use a Target instead of a RequestListener to set your image which in turn will avoid using submit() to load data into views or items on the UI thread.
This issue has been automatically marked as stale because it has not had activity in the last seven days. It will be closed if no further activity occurs within the next seven days. Thank you for your contributions.
Thanks for reply, can we have warning or error on android studio for this ? I guess it is easy for someone to have a bug if dont know about it.
I'm not able to add warnings or errors to Android Studio unfortunately. What made you decide to use RequestListener instead of Target? If there's some documentation we could correct or clarify I'd be happy to do so.
This issue has been automatically marked as stale because it has not had activity in the last seven days. It will be closed if no further activity occurs within the next seven days. Thank you for your contributions.
Thanks @sjudd, we already change our implementation to Target. Appreciate your help.
Most helpful comment
Use a Target instead of a RequestListener to set your image which in turn will avoid using submit() to load data into views or items on the UI thread.