问题
I have a Horizontal RecyclerView: each item has an image loaded into it using the Facebook Fresco image library. However, while the correct image loads initially as it is scrolled a bit onto the screen, it disappears when the RecyclerView is scrolled further.
In addition, there are issues where scrolling back and forth puts the wrong image in the wrong item (I assume this is an issue with recycling the viewholders). That said, the text you can see overlaying the items in the below screen shot always displays consistently on the correct item, so this recycling issue is exclusive to the images.
I can confirm I am passing the SimpleDraweeView the correct URL each time.
Below are some screens and accompanying logs:
Screenshot 1: showing the correct image entering from the right.
Logs as this is scrolled onto the screen and the image is successfully loaded:
AbstractDraweeController: controller cbb6b5b 5: onTouchEvent MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=32.860107, y[0]=198.16406, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=464189, downTime=464189, deviceId=0, source=0x1002 }
AbstractDraweeController: controller c077610 8: setHierarchy: com.facebook.drawee.generic.GenericDraweeHierarchy@d36ab12
AbstractDraweeController: controller 87baf9c null -> 9: initialize
AbstractDraweeController: controller c077610 8: setHierarchy: null
AbstractDraweeController: controller 87baf9c 9: setHierarchy: com.facebook.drawee.generic.GenericDraweeHierarchy@d36ab12
AbstractDraweeController: controller 87baf9c 9: onAttach: request needs submit
PipelineDraweeController: controller 87baf9c: getDataSource
AbstractDraweeController: controller 87baf9c 9: submitRequest: dataSource: ad37da5
BufferedDiskCache: Did not find image for http://i.imgur.com/OVwFM9ub.jpg in staging area
BufferedDiskCache: Disk cache read for http://i.imgur.com/OVwFM9ub.jpg
BufferedDiskCache: Found entry in disk cache for http://i.imgur.com/OVwFM9ub.jpg
NativeMemoryChunkPool: Used = (7, 188416); Free = (0, 0)
NativeMemoryChunkPool: get (alloc) (object, size) = (ef2f57a, 16384)
GenericByteArrayPool: Used = (1, 16384); Free = (0, 0)
GenericByteArrayPool: get (reuse) (object, size) = (cf34727, 16384)
GenericByteArrayPool: release (reuse) (object, size) = (cf34727, 16384)
GenericByteArrayPool: Used = (0, 0); Free = (1, 16384)
BufferedDiskCache: Successful read from disk cache for http://i.imgur.com/OVwFM9ub.jpg
TiffUtil: Unsupported orientation
BitmapPool: Used = (7, 2831360); Free = (0, 0)
BitmapPool: get (alloc) (object, size) = (8622988, 102400)
AbstractDraweeController: controller 87baf9c 9: set_final_result @ onNewResult: image: CloseableReference 1a34f21
Screenshot 2: showing the RecyclerView after scrolling further from right to left. This shows the image that was previously loaded into the ViewHolder has now disappeared.
The following logs are produced between Screenshot 1 and 2:
AbstractDraweeController: controller cbb6b5b 5: onTouchEvent MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=103.65283, y[0]=144.14063, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=793409, downTime=793409, deviceId=0, source=0x1002 }
AbstractDraweeController: controller 87baf9c 9: onDetach
AbstractDraweeController: controller e14aa9d 2: onDetach
AbstractDraweeController: controller 87baf9c 9: release: image: CloseableReference 1a34f21
AbstractDraweeController: controller e14aa9d 2: release: image: CloseableReference 61f0be9
Code: ViewHolder XML
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_width="120dp"
android:layout_height="match_parent"
android:background="#993366">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/recycler_drawee_view"
android:layout_width="110dp"
android:layout_height="match_parent"
android:background="#336699"
fresco:placeholderImage="@drawable/placeholder" />
<TextView
android:id="@+id/recycler_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TEST" />
</FrameLayout>
Code: SimpleDraweeView setup
GenericDraweeHierarchyBuilder builder =
new GenericDraweeHierarchyBuilder(context.getResources());
mHierarchy = builder
.setFadeDuration(300)
.setPlaceholderImage(context.getDrawable(R.drawable.placeholder))
.build();
...
mDraweeView.setHierarchy(mHierarchy);
Uri uri = Uri.parse(imageLink);
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(uri)
.build();
mDraweeView.setController(controller);
Code: RecyclerView.Adapter
@Override
public SimpleHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(mContext).inflate(R.layout.recycler_view_item, viewGroup, false);
return new SimpleHolder(view, mHierarchy);
}
...
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
holder.setText(EntryUtils.getFullCaption(mData.get(position)));
holder.setImage(EntryUtils.getThumbnailLink(mData.get(position)));
}
Thanks again.
回答1:
From the logcat you can see that you are using the same instance of DraweeHierarchy with multiple controllers. Do not do that.
AbstractDraweeController: controller c077610 8: setHierarchy: com.facebook.drawee.generic.GenericDraweeHierarchy@d36ab12
AbstractDraweeController: controller 87baf9c null -> 9: initialize
AbstractDraweeController: controller c077610 8: setHierarchy: null
AbstractDraweeController: controller 87baf9c 9: setHierarchy: com.facebook.drawee.generic.GenericDraweeHierarchy@d36ab12
As explained in the documentation, do not re-use DraweeHierarchies
. Each DraweeView
needs to have its own instance of a DraweeHierarchy
. Do not store the hierarchy in mHierarchy
, just set the hierarchy to the view.
Also, each view needs its own hierarchy but that doesn't mean you have to build a new hierarchy each time you want to set a new image. You build the hierarchy only once, when you create the view and that's it. Later on when you need to set/change an image, just set a new controller to the view.
From your example it seems that you do not need to build the hierarchy programmatically at all. You can specify both the fade duration and the placeholder in XML. Btw, default value for fade-duration is 300ms so you can actually omit that part too.
So, just remove the code that builds and sets the hierarchy (mDraweeView.setHierarchy(mHierarchy)
).
If you are only using the Uri without any additional options, you do not need to build the controller. Just do mDraweeView.setImageURI(uri)
and SimpleDraweeView
will create the controller for you.
来源:https://stackoverflow.com/questions/34711792/fresco-images-dissapear-after-scrolling-recylcerview