3

私は Horizo​​ntal RecyclerView を持っています。各アイテムには、Facebook Fresco 画像ライブラリを使用して読み込まれた画像があります。ただし、画面に少しスクロールすると正しい画像が最初に読み込まれますが、RecyclerView をさらにスクロールすると画像が消えます。

さらに、前後にスクロールすると、間違ったアイテムに間違った画像が表示されるという問題があります (これは、ビューホルダーのリサイクルに関する問題だと思います)。とはいえ、下のスクリーン ショットでアイテムに重ねて表示されているテキストは常に正しいアイテムに一貫して表示されるため、このリサイクルの問題は画像に限定されます。

毎回 SimpleDraweeView に正しい URL を渡していることを確認できます。

以下は、いくつかの画面と付随するログです。

スクリーンショット 1、右から入る画像を示す

スクリーンショット 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)));
}
ここまでお時間をいただき、ありがとうございました。詳細が役立つかどうかお知らせください。提供できるように努めます。

再度、感謝します。

4

1 に答える 1

3

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

ドキュメントで説明されているように、再利用しないでくださいDraweeHierarchies。それぞれDraweeViewに の独自のインスタンスが必要DraweeHierarchyです。階層を に保存しないでくださいmHierarchy。階層をビューに設定するだけです。

また、各ビューには独自の階層が必要ですが、新しい画像を設定するたびに新しい階層を構築する必要があるわけではありません。ビューを作成するときに一度だけ階層を構築するだけです。後で画像を設定/変更する必要がある場合は、新しいコントローラーをビューに設定するだけです。

あなたの例から、プログラムで階層を構築する必要はまったくないようです。フェード時間とプレースホルダーの両方を XML で指定できます。ちなみに、fade-duration のデフォルト値は 300ms なので、実際にはその部分も省略できます。したがって、階層を構築および設定するコードを削除するだけです ( mDraweeView.setHierarchy(mHierarchy))。

追加オプションなしで Uri のみを使用している場合は、コントローラーをビルドする必要はありません。実行するだけmDraweeView.setImageURI(uri)SimpleDraweeView、コントローラーが作成されます。

于 2016-01-27T18:41:35.390 に答える