RecyclerView
を含むリストを表示するためにimageView
を使用しています。 UIをより流makeにするには、SDカードに保存された58dpのサムネイルをasyncTask
でこれらのimageViewsにロードします。
問題は、childView
が視覚的に表示されると、別のデータの古いイメージが再利用され、AsyncTask
が終了すると置き換えられることです。 imageView
でonPreExecute
ビットマップをnullに設定することでシャッフルを停止できます。
古い画像を本当に再利用する方法はありますか、それとも新しいView
が配置されるたびにSDカードから画像をロードする必要がありますか?これは、最初に間違った画像があるか、画像が真っ白であるため、ビューを非常に見苦しくします。
ビューを再利用するため、コンテンツが既に含まれているビューを取得するため、ListViews
パターンを使用している場合は、これもViewHolder
で問題になります。
ここには2つの解決策があります。良い習慣と悪いハックです。
bindViewHolder(VH holder, int position)
などを使用して、setDrawable(null)
の先頭に何も表示しないようにImageView
を設定することをお勧めします。
不正なハックでは、ViewHolder
パターンを強制せずにビューをリサイクル/再利用せず、毎回それを膨張させますが、それはListView
および他の古いコンポーネントでのみ許可されます。
ユニバーサルイメージローダー を確認する必要があります。メモリキャッシュ、ディスクキャッシュがあり、画像を非同期に読み込むため、UIをブロックしません。デフォルトの画像を設定したり、画像の取得に失敗したりできます。画像をサンプリングして、ビットマップのメモリフットプリントを減らすことができます。画像に使用することをお勧めします。
無意味であるため、ケースでリサイクル可能を無効にしないでください。適切にサンプリングされない場合、ビットマップドロウアブルは非常に高いメモリオーバーロードを生成するため、画像はリサイクルする必要があります。
RecyclerViewAdapterの使用例:
@Override
public void onBindViewHolder(CustomViewHolder viewHolder, int position) {
String imageUri = "";//local or remote image uri address
//viewHolder.imgView: reference to your imageview
//before you call the displayImage you have to
//initialize imageloader in anywhere in your code for once.
//(Generally done in the Application class extender.)
ImageLoader.getInstance().displayImage(imageUri, viewHolder.imgView);
}
編集:最近、私はGlideをメインの画像読み込みおよびキャッシュライブラリとして考えています。次のように使用できます。
Glide.with(context)
.load(imageUri)
.placeholder(R.drawable.myplaceholder)
.into(imageView);
新しいリクエストを開始する前に古いリクエストをキャンセルしてくださいスクロールと小さな画像)。
解決策は次のとおりです。
RxJavaを使用してバックグラウンドでアプリからアイコンを読み込む例:
public void loadIcon(final ImageView appIconView, final ApplicationInfo appInfo, final String uniqueAppID) {
Single.fromCallable(() -> {
return appIconView.getContext().getPackageManager().getApplicationIcon(appInfo);
})
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe( drawable -> {
if (uniqueAppID.equals(mUniqueAppID)) { // Show always the correct app icon
appIconView.setImageDrawable(drawable);
}
}
);
}
ここで、mUniqueAppIDは、onBindViewHolderによって変更されたビューホルダーのフィールドです。
「onBindViewHolder」メソッドで古いリクエストをキャンセルする必要があります。
try{
((SpecialOfferViewHolder)viewHolder).imageContainer.cancelRequest();
}catch(Exception e) {
}
viewHolderに画像コンテナを保存することを忘れないでください:
public void onResponse(ImageContainer response, boolean arg1) {
((SpecialOfferViewHolder)viewHolder).imageContainer=response;
}
私はグッドプラクティスに追加します:
良い習慣では、setDrawable(null)などを使用して、bindViewHolder(VHホルダー、int位置)の先頭に何も表示しないようにImageViewを設定します。
何も表示するのではなく、ローダーの画像を表示して、そのビューで処理が行われ、しばらくして結果が表示されるというフィードバックをユーザーに提供します。空白のビューのみを表示するのは良い習慣ではありません。ユーザーにフィードバックを提供する必要があります。