其實就是Adapter中可以被覆寫的兩個方法
1、onDetachedFromRecyclerView
看下方法說明
/**
* Called by RecyclerView when it stops observing this Adapter.
*
* @param recyclerView The RecyclerView instance which stopped observing this adapter.
* @see #onAttachedToRecyclerView(RecyclerView)
*/
public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
}
在RecyclerView不再觀察這個Adapter時被調(diào)用。
與之對應的是onAttachedToRecyclerView
:
/**
* Called by RecyclerView when it starts observing this Adapter.
* <p>
* Keep in mind that same adapter may be observed by multiple RecyclerViews.
*
* @param recyclerView The RecyclerView instance which started observing this adapter.
* @see #onDetachedFromRecyclerView(RecyclerView)
*/
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
}
在RecyclerView開始觀察這個Adapter時,被調(diào)用捺萌。
通常我們的理解是這樣的:
頁面進入時,顯示RecyclerView护桦,調(diào)用onAttachedToRecyclerView
廊宪,做一些注冊工作;
頁面退出時懈玻,銷毀RecyclerView巧婶,調(diào)用onDetachedFromRecyclerView
,做一些解注冊和其他資源回收的操作。
而實際上艺栈,這兩個方法的調(diào)用時機是:
public void setAdapter(Adapter adapter) {
// bail out if layout is frozen
...
setAdapterInternal(adapter, false, true);
...
}
private void setAdapterInternal(Adapter adapter, boolean compatibleWithPrevious,
boolean removeAndRecycleViews) {
if (mAdapter != null) {
mAdapter.unregisterAdapterDataObserver(mObserver);
mAdapter.onDetachedFromRecyclerView(this);//這里onDetachedFromRecyclerView
}
if (!compatibleWithPrevious || removeAndRecycleViews) {
removeAndRecycleViews();
}
mAdapterHelper.reset();
final Adapter oldAdapter = mAdapter;
mAdapter = adapter;
if (adapter != null) {
adapter.registerAdapterDataObserver(mObserver);
adapter.onAttachedToRecyclerView(this);//這里onAttachedToRecyclerView
}
if (mLayout != null) {
mLayout.onAdapterChanged(oldAdapter, mAdapter);
}
mRecycler.onAdapterChanged(oldAdapter, mAdapter, compatibleWithPrevious);
mState.mStructureChanged = true;
}
可以看到英岭,在調(diào)用setAdapter方法時,新設置的Adapter會調(diào)用onAttachedToRecyclerView
湿右,原有的Adapter會調(diào)用onDetachedFromRecyclerView
巴席。
所以如果覆寫了onDetachedFromRecyclerView
,為了確保被調(diào)用诅需,需要在頁面退出時漾唉,手動調(diào)用setAdapter(null)
。
2堰塌、onViewDetachedFromWindow
方法說明:
/**
* Called when a view created by this adapter has been detached from its window.
*
* <p>Becoming detached from the window is not necessarily a permanent condition;
* the consumer of an Adapter's views may choose to cache views offscreen while they
* are not visible, attaching and detaching them as appropriate.</p>
*
* @param holder Holder of the view being detached
*/
public void onViewDetachedFromWindow(@NonNull VH holder) {
}
簡言之赵刑,就是當itemView被從window上detach時調(diào)用〕⌒蹋看起來很美好般此,與之對應的方法是:
/**
* Called when a view created by this adapter has been attached to a window.
*
* <p>This can be used as a reasonable signal that the view is about to be seen
* by the user. If the adapter previously freed any resources in
* {@link #onViewDetachedFromWindow(RecyclerView.ViewHolder) onViewDetachedFromWindow}
* those resources should be restored here.</p>
*
* @param holder Holder of the view being attached
*/
public void onViewAttachedToWindow(@NonNull VH holder) {
}
然后我們也如第一個方法般調(diào)用了:
onViewAttachedToWindow
中做一些注冊工作;
onViewDetachedFromWindow
中做一些解注冊和釋放資源的工作牵现。
在RecyclerView正常滾動時铐懊,這兩個方法都會被調(diào)用。然而頁面退出時瞎疼,onViewDetachedFromWindow
并不會被調(diào)用科乎!
追根溯源,會發(fā)現(xiàn)癥結在LinearLayoutManager中:
@Override
public void onDetachedFromWindow(RecyclerView view, RecyclerView.Recycler recycler) {
super.onDetachedFromWindow(view, recycler);
if (mRecycleChildrenOnDetach) {
removeAndRecycleAllViews(recycler);
recycler.clear();
}
}
默認mRecycleChildrenOnDetach=false
贼急。我們需要調(diào)用setRecycleChildrenOnDetach(true)
才能實現(xiàn)在頁面退出時茅茂,依然調(diào)用onViewDetachedFromWindow
方法。
整合RecyclerView
可以設計一個RecyclerView的基類太抓,在基類中做如下處理:
public class BaseRecyclerView extends RecyclerView implements LifecycleObserver {
public BaseRecyclerView(@NonNull Context context) {
super(context);
init(context);
}
public BaseRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public BaseRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
if (context instanceof LifecycleOwner) {
((LifecycleOwner) context).getLifecycle().addObserver(this);
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onDestory() {
/*
確保Adapter#onDetachedFromRecyclerView被調(diào)用
*/
setAdapter(null);
}
@Override
public void setLayoutManager(LayoutManager layoutManager) {
super.setLayoutManager(layoutManager);
if (layoutManager instanceof LinearLayoutManager) {
/*
確保Adapter#onViewDetachedFromWindow被調(diào)用
*/
((LinearLayoutManager) layoutManager).setRecycleChildrenOnDetach(true);
}
}
}