Fresco:滚动 RecyclerView 后图像消失
Fresco: Images dissapear after scrolling RecylcerView
我有一个 Horizontal RecyclerView:每个项目都使用 Facebook Fresco 图片库加载了一张图片。然而,虽然正确的图像最初是在滚动到屏幕上时加载的,但当 RecyclerView 进一步滚动时它会消失。
此外,还存在来回滚动将错误图像放入错误项目的问题(我认为这是回收 viewholders 的问题)。也就是说,您可以在下面的屏幕截图中看到覆盖项目的文本始终一致地显示在正确的项目上,因此此回收问题仅针对图像。
我可以确认我每次都将正确的 URL 传递给 SimpleDraweeView。
下面是一些屏幕和随附的日志:
屏幕截图 1:显示从右侧进入的正确图像。
滚动到屏幕上并且图像已成功加载时的日志:
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
屏幕截图 2:显示从右向左进一步滚动后的 RecyclerView。这表明之前加载到 ViewHolder 中的图像现在已经消失。
屏幕截图 1 和 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
代码:
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>
代码:SimpleDraweeView 设置
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);
代码: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)));
}
如果你走到这一步,谢谢你的时间。如果进一步的详细信息可能有用,请告诉我,我会尽力提供。
再次感谢。
从 logcat 可以看出,您正在使用具有多个控制器的同一个 DraweeHierarchy 实例。不要那样做。
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
如documentation中所述,不要re-useDraweeHierarchies
。每个 DraweeView
都需要有自己的 DraweeHierarchy
实例。不要在mHierarchy
中存储层次结构,只需将层次结构设置到视图即可。
此外,每个视图都需要自己的层次结构,但这并不意味着每次要设置新图像时都必须构建新的层次结构。当您创建视图时,您只构建一次层次结构,仅此而已。稍后当您需要 set/change 图像时,只需为视图设置一个新控制器即可。
从您的示例来看,您似乎根本不需要以编程方式构建层次结构。您可以在 XML 中指定淡入淡出持续时间和占位符。顺便说一句,fade-duration 的默认值为 300 毫秒,因此您实际上也可以省略该部分。
因此,只需删除构建和设置层次结构的代码 (mDraweeView.setHierarchy(mHierarchy)
)。
如果您只使用 Uri 而没有任何其他选项,则不需要构建控制器。只需执行 mDraweeView.setImageURI(uri)
,SimpleDraweeView
将为您创建控制器。
我有一个 Horizontal RecyclerView:每个项目都使用 Facebook Fresco 图片库加载了一张图片。然而,虽然正确的图像最初是在滚动到屏幕上时加载的,但当 RecyclerView 进一步滚动时它会消失。
此外,还存在来回滚动将错误图像放入错误项目的问题(我认为这是回收 viewholders 的问题)。也就是说,您可以在下面的屏幕截图中看到覆盖项目的文本始终一致地显示在正确的项目上,因此此回收问题仅针对图像。
我可以确认我每次都将正确的 URL 传递给 SimpleDraweeView。
下面是一些屏幕和随附的日志:
屏幕截图 1:显示从右侧进入的正确图像。
滚动到屏幕上并且图像已成功加载时的日志:
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
屏幕截图 2:显示从右向左进一步滚动后的 RecyclerView。这表明之前加载到 ViewHolder 中的图像现在已经消失。
屏幕截图 1 和 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
代码: 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>
代码:SimpleDraweeView 设置
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);
代码: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)));
}
再次感谢。
从 logcat 可以看出,您正在使用具有多个控制器的同一个 DraweeHierarchy 实例。不要那样做。
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
如documentation中所述,不要re-useDraweeHierarchies
。每个 DraweeView
都需要有自己的 DraweeHierarchy
实例。不要在mHierarchy
中存储层次结构,只需将层次结构设置到视图即可。
此外,每个视图都需要自己的层次结构,但这并不意味着每次要设置新图像时都必须构建新的层次结构。当您创建视图时,您只构建一次层次结构,仅此而已。稍后当您需要 set/change 图像时,只需为视图设置一个新控制器即可。
从您的示例来看,您似乎根本不需要以编程方式构建层次结构。您可以在 XML 中指定淡入淡出持续时间和占位符。顺便说一句,fade-duration 的默认值为 300 毫秒,因此您实际上也可以省略该部分。
因此,只需删除构建和设置层次结构的代码 (mDraweeView.setHierarchy(mHierarchy)
)。
如果您只使用 Uri 而没有任何其他选项,则不需要构建控制器。只需执行 mDraweeView.setImageURI(uri)
,SimpleDraweeView
将为您创建控制器。