从未调用过RecyclerView.Adapter onViewDetachedFromWindow

Dok*_*ans 6 android adapter android-recyclerview

如果我希望我的ViewHolders在RecyclerView中清理内部状态(在这种情况下从EventBus取消注册并清理Rx-Subscriptions),那么该怎么办?我认为方法onViewDetachedFromWindowonViewRecycled适配器中的方法是我可以清理资源的回调(如API中所述),但是当我从Activity使用RecyclerView另一个更改时,从不调用此方法Activity.

只有onViewAttachedToWindow在输入活动时才会调用,我可以看到我的项目.

我的适配器看起来像这样:

public class Adapter extends RecyclerView.Adapter<MyViewHolder> 
{
    @Override 
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return factory.getViewholder(parent, viewType, this);
    }

    @Override 
    public void onBindViewHolder(MyViewHolder holder, int position) {
        MyItem item = items.get(position);
    holder.bind(item);
    }

    @Override
    public void onViewDetachedFromWindow(MyViewHolder holder)
    {
        holder.viewDetached();
        super.onViewDetachedFromWindow(holder);
    }

    @Override
    public void onViewAttachedToWindow(MyViewHolder holder)
    {  
        super.onViewAttachedToWindow(holder);
        holder.viewAttached();
    }

    @Override
    public void onViewRecycled(MyViewHolder holder)
    {
        super.onViewRecycled(holder);
        holder.viewRecycled();
    }

    @Override 
    public int getItemCount() {
        return items.size();
    }

    @Override
    public int getItemViewType(int position)
    {
        return items.get(position).getType(this.factory);
    }
}
Run Code Online (Sandbox Code Playgroud)

ActivityRecyclerView:

public class MyActivity extends AppCompatActivity
{

   protected void setupView()
   {
        //called in onCreate

        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
        this.adapter = new Adapter(new ItemViewHolderFactory());
   }

    @Override
    public void setItems(List<MyItem> items)
    {
        //items are loaded async
        this.adapter.setItems(items);
        this.recyclerView.setAdapter(this.adapter);
        this.recyclerView.scheduleLayoutAnimation();
    }
}
Run Code Online (Sandbox Code Playgroud)

ViewHolder看起来像这样

public class MyViewHolder extends RecyclerView.ViewHolder
{
        public void bind(MyItem item)
        {
          //set initial data
        }

       public void viewAttached()
       {
        registerToEventBus();
        loadDataAsync(); // here an rx operation is scheduled and a subscription is hold
       }

     public void viewDetached()
     {
         unregisterFromEventBus();
         cancelAsyncOperationAndCleanSubscription();
     }
}
Run Code Online (Sandbox Code Playgroud)

感谢您的任何建议.

编辑 我试图onDetachedFromRecyclerView在适配器中覆盖,但也没有调用此方法.

eug*_*man 5

我遇到了同样的问题:

如前所述,您可以在onPause(活动,片段)或onDetachFromWindow(活动,片段)中将适配器设置为null

recyclerview.setAdapter(null)
Run Code Online (Sandbox Code Playgroud)

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

另一种可能性是在工厂中为自定义视图而不是仅布局进行充气。然后,您可以在自定义视图onDetachFromWindow()中进行清理。您也可以将onDetachedFromWindow设置为null。