I am Trying to implement Glide in a CustomAdapter class onBindViewHolder() method for RecyclerView which results in following error--->" You must not call setTag() on a view Glide is targeting"
Referred https://github.com/bumptech/glide/issues/370
But I couldn't solve the issue...
Here is my usage
public void onBindViewHolder(final MyViewHolder holder, final int listPosition) {
TextView textViewName = holder.textViewName;
TextView textViewVersion = holder.textViewVersion;
ImageView imageView = holder.imageViewIcon;
DataModel dataModel = dataSet.get(listPosition);
textViewName.setText(dataModel.getName());
textViewVersion.setText(dataModel.getVersion());
Glide
.with(mContext)
.load(dataModel.getImage())
.into(imageView);
}
After failure and much trial I decided to try Picasso
Which worked flawless ......
public void onBindViewHolder(final MyViewHolder holder, final int listPosition) {
TextView textViewName = holder.textViewName;
TextView textViewVersion = holder.textViewVersion;
ImageView imageView = holder.imageViewIcon;
DataModel dataModel = dataSet.get(listPosition);
textViewName.setText(dataModel.getName());
textViewVersion.setText(dataModel.getVersion());
Picasso
.with(mContext)
.load(dataModel.getImage())
.into(imageView);
}
Please guide where I am going wrong with Glide.
Glide Version: com.github.bumptech.glide:glide:3.7.0
Layout XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:tag="cards main container"
android:scrollbars="none">
<android.support.v7.widget.CardView
android:id="@+id/card_view"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="@color/color_white"
card_view:cardCornerRadius="0dp"
card_view:cardElevation="2dp"
card_view:cardUseCompatPadding="true"
android:scrollbars="none"
android:layout_marginBottom="3dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<ImageView
android:scaleType="fitStart"
android:adjustViewBounds="true"
android:id="@+id/imageView"
android:tag="image_tag"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:layout_weight="1"
android:src="@drawable/ic_launcher"/>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
Stack trace / LogCat:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.journaldev.recyclerviewcardview, PID: 2289
java.lang.IllegalArgumentException: You must not call setTag() on a view Glide is targeting
at com.bumptech.glide.request.target.ViewTarget.getRequest(ViewTarget.java:133)
at com.bumptech.glide.GenericRequestBuilder.into(GenericRequestBuilder.java:650)
at com.bumptech.glide.GenericRequestBuilder.into(GenericRequestBuilder.java:697)
at com.bumptech.glide.DrawableRequestBuilder.into(DrawableRequestBuilder.java:448)
at com.journaldev.recyclerviewcardview.CustomAdapter.onBindViewHolder(CustomAdapter.java:75)
at com.journaldev.recyclerviewcardview.CustomAdapter.onBindViewHolder(CustomAdapter.java:24)
at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5825)
at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5858)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5094)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4970)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2029)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1414)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1377)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:578)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3315)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3124)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3568)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1079)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.support.v7.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:433)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:724)
at android.view.View.layout(View.java:17520)
at android.view.ViewGroup.layout(ViewGroup.java:5612)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2342)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2069)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1246)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6301)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:871)
at android.view.Choreographer.doCallbacks(Choreographer.java:683)
at android.view.Choreographer.doFrame(Choreographer.java:619)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:857)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
E/AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Huh, the related #370 wouldn't solve this, because your ImageView is not the root of the layout. However it would be interesting to know what is causing trouble. Try to add this:
try {
Glide
.with(mContext)
.load(dataModel.getImage())
.into(imageView);
} catch(IllegalArgumentException ex) {
Log.wtf("Glide-tag", String.valueOf(imageView.getTag()));
}
Oh, actually after writing the above I saw android:tag="image_tag", just remove that.
@TWiStErRob Thank you
But picasso could work without any issue... why cant you implement similar in glide
Because Glide is not Picasso. The internals are totally different. If everything was done the same way there would be no point in co-existing. A quick look at Picasso, it doesn't have scoping and it requires the target view to implement hashCode/equals correctly (see Picasso.targetToAction). In Glide Targets are really abstract, and they wrap the views. The view is not the actual target, ViewTarget is just one of many possible implementations of Target. This gives extreme flexibility to advanced use cases for example you can create a target for an ImageView in a RemoteViews.
You can use ViewTarget.setTagId if you really need that tag there and it bothers you.
Recently I came into this problem in my project when I began to replace Picasso with Glide.Then I've to replace all my method setTag(Object tag) with setTag(int key, Object tag). That really could drive me to crazy. I guess the Glide use the root view's setTag(Object tag) method to do something. The android view has another similar method: setTag(int key, Object tag). As the previous method is universally used in view holder. Why not Glide use the second method with a specific int key to avoid conflict
s? I think that's a costless way to optimize
the function. (ps.I'm not English native speaker.Just ignore my errors in the post.)
@ilioili that's exactly what ViewTarget.setTagId does, read the source of that class.
See also http://stackoverflow.com/a/35096552/253468 for walkthrough.
ViewTarget.setTagId(R.id.xxx_you_self_id_for_glide), this funcation can change the default tagId for Glide. And then, you View can set its own tagId, for example in ViewHolder.
Most helpful comment
@ilioili that's exactly what
ViewTarget.setTagIddoes, read the source of that class.See also http://stackoverflow.com/a/35096552/253468 for walkthrough.