RecyclerView适配器的生命周期是什么?

时间:2016-06-07 08:50:37

标签: android android-recyclerview android-lifecycle

我正在从适配器中的演示者请求图像:

 // Called when the url of a tab changes.
function checkForValidUrl(tabId, changeInfo, tab) {

  if (tab.url.indexOf('calendar') > -1) {

         chrome.tabs.insertCSS(null, {code: '.ui-sch input { direction: rtl }'});
         chrome.tabs.insertCSS(null, {code: '.ui-sch textarea { direction: rtl }'});
  }
};

// Listen for any changes to the URL of any tab.
chrome.tabs.onUpdated.addListener(checkForValidUrl);

我应该在重新使用 @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); }) ); } 时取消订阅。这很容易。

但是当视图被销毁时如何停止所有订阅?我也应该使演示者引用无效以避免内存泄漏

3 个答案:

答案 0 :(得分:20)

我认为最好的办法是:

  1. subscription
  2. 中保留SiteAdapter.ViewHolder引用
  3. unsubscribe subscription onBindViewHolder中的ViewHolder对象(重新使用CompositeSubscription时调用此对象)
  4. adapter对象保留在onDetachedFromRecyclerView
  5. 使用Adapter的{​​{1}}方法unsubscribe compositeSubscription
  6. 像这样:

    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
            }
        }
    }
    

答案 1 :(得分:2)

可以调用public void onViewRecycled(@NonNull VH holder) enter image description here

答案 2 :(得分:1)

对于其他有相同问题的用户: 仅当将适配器在onPause(活动,片段)或onDetachFromWindow(活动,片段)中设置为null时,才调用适配器中的viewDetachedFromWindow

recyclerview.setAdapter(null)

然后您获得viewDetachedFromWindow(...),可以在其中释放内部状态和订阅。我会在绑定上设置您的订阅,请确保在释放您的每个绑定调用之前释放旧订阅,因为视图可以回收。

另一种可能性是在工厂中增加自定义视图,而不是仅增加布局。然后,您可以在自定义视图onDetachFromWindow()中进行清理。您也可以在不将适配器设置为null的情况下获得onDetachedFromWindow。