アダプタのプレゼンターに画像を要求しています:
@Override
public void onBindViewHolder(SiteAdapter.ViewHolder holder, int position)
{
Site site = sites.get(position);
holder.siteName.setText(site.getName());
requestHolderLogo(holder, site.getLinks().getLogoUrl());
}
private void requestHolderLogo(final ViewHolder holder, final String logoUrl)
{
compositeSubscription.add(
presenter.bitmap(logoUrl)
.subscribe(
bitmap -> {
holder.siteLogo.setImageBitmap(bitmap);
holder.siteLogo.setVisibility(View.VISIBLE);
},
error -> {
holder.siteName.setVisibility(View.VISIBLE);
})
);
}
ViewHolder
が再利用されたときに登録を解除する必要があります。簡単です。
しかし、ビューが破棄されたときにすべてのサブスクリプションを停止する方法は?また、おそらくメモリリークを避けるためにプレゼンターの参照を無効にする必要があります
そのための最善の方法は次のとおりだと思います。
SiteAdapter.ViewHolder
にsubscription
参照を保持しますunsubscribe
subscription
内のonBindViewHolder
オブジェクト(ViewHolder
が再利用されるときに呼び出されます)CompositeSubscription
オブジェクトをadapter
に保持しますonDetachedFromRecyclerView
のAdapter
メソッドをunsubscribe
からcompositeSubscription
に使用しますそのようです:
public class SiteAdapter extends RecyclerView.Adapter<SiteAdapter.ViewHolder> {
private CompositeSubscription compositeSubscription = new CompositeSubscription();
// other needed SiteAdapter methods
@Override
public void onBindViewHolder(SiteAdapter.ViewHolder holder, int position) {
if (holder.subscription != null && !holder.subscription.isUnsubscribed()) {
compositeSubscription.remove(holder.subscription);
// this will unsubscribe the subscription as well
}
Site site = sites.get(position);
holder.siteName.setText(site.getName());
requestHolderLogo(holder, site.getLinks().getLogoUrl());
}
private void requestHolderLogo(final SiteAdapter.ViewHolder holder, final String logoUrl) {
holder.subscription = presenter.bitmap(logoUrl)
.subscribe(
bitmap -> {
holder.siteLogo.setImageBitmap(bitmap);
holder.siteLogo.setVisibility(View.VISIBLE);
},
error -> {
holder.siteName.setVisibility(View.VISIBLE);
});
compositeSubscription.add(holder.subscription);
}
@Override
public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
compositeSubscription.unsubscribe();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public Subscription subscription;
// some holder-related stuff
public ViewHolder(View itemView) {
super(itemView);
// init holder
}
}
}
同じ問題がある他の場合:アダプタのviewDetachedFromWindowは、アダプタがonPause(アクティビティ、フラグメント)またはonDetachFromWindow(アクティビティ、フラグメント)でnullに設定されている場合にのみ呼び出されます。
recyclerview.setAdapter(null)
次に、viewDetachedFromWindow(...)を取得して、内部状態とサブスクリプションを解放できます。バインド時にサブスクリプションを設定します。ビューをリサイクルできるように、すべてのバインド呼び出しの前に古いサブスクリプションを解放するようにしてください。
別の可能性は、工場内のレイアウトだけではなく、カスタムビューを膨らませることです。次に、カスタムビューonDetachFromWindow()でクリーンアップを実行できます。アダプタをnullに設定せずにonDetachedFromWindowも取得します。