如果视图计数较小,RecyclerView 不会回收视图
RecyclerView not recycling views if the view count is small
我一直在处理 Recycler View 中的一个奇怪行为,如果适配器中的视图计数很小,在我的大小为 5 的情况下,视图不会被回收并且当视图被调用时不会调用 onBindViewHolder滚动回屏幕。例如,如果我将大小增加到 10 个视图,则回收开始工作并且每次视图进入屏幕时都会调用 onBindViewHolder。
XML
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeRefresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<!-- RECYCLER VIEW -->
<android.support.v7.widget.RecyclerView
android:id="@+id/eventsList"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
Recycler 视图初始化
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
llm.setOrientation(LinearLayoutManager.VERTICAL);
eventsList.setLayoutManager(llm);
//Sets endless listener
scrollListener = new EndlessRecyclerOnScrollListener(llm,3,mLastDownloadedPage) {
@Override
public void onLoadMore(int current_page) {
Timber.d("Loading date for page: " + current_page);
mLastDownloadedPage = current_page;
//If it's showing cached don't download
if(showingCached)
return;
//Shows snackbar loading view
showSnackbarLoadingView();
//Gets events
getEvents(false);
}
};
//eventsList.addOnScrollListener(scrollListener);
//Set the adapter
mAdapter = new EventListAdapter(this,getActivity().getApplicationContext());
eventsList.setAdapter(mAdapter);
适配器
@Override
public EventHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
Timber.d("Create view holder pos: "+i);
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_events_row, viewGroup, false);
return new EventHolder(v,mListener);
}
@Override
public void onBindViewHolder(EventHolder eventHolder, int i) {
if(mBindListener != null)
mBindListener.onBind(eventHolder,i);
Timber.d("Bind view holder pos "+i);
Event event = eventList.get(i);
eventHolder.bindEvent(event);
//Sets the date
setDate(eventHolder.date, event);
//Sets the location
setLocation(eventHolder.distance,event);
}
在屏幕上只有 3 个可见视图,大小为 5,当我向下滚动时,我可以看到 createViewHolder
和 bindViewHolder
被调用用于位置 4 和 5,但是当我滚动到顶部时,退出屏幕时它们不会被回收。我可以确认,因为通过覆盖
@Override
public void onViewRecycled(EventHolder holder) {
super.onViewRecycled(holder);
Timber.d("onViewRecycled: "+holder.name);
}
没有记录任何消息。但是,如果视图计数增加,例如大小为 10,则一切正常,视图被回收并且每个位置都调用 onBindViewHolder
。
这是正常行为吗?如果是如何保存item view的状态,比如activated状态,我以前是把active位置保存在一个变量里,然后用bind方法进入screen时用这一行激活view
holder.itemView.setActivated(pos == lastSelectedPos);
这是正常行为,但您可以通过以下方式对其进行调整:
recyclerView.setItemViewCacheSize(int);
关于问题的第二部分 - 你是对的!将 "activated" 位置存储为适配器中的变量。在 onBindViewHolder() 中做类似的事情:
holder.itemView.setActivated(holder.getAdapterPosition() == lastSelectedPos);
我一直在处理 Recycler View 中的一个奇怪行为,如果适配器中的视图计数很小,在我的大小为 5 的情况下,视图不会被回收并且当视图被调用时不会调用 onBindViewHolder滚动回屏幕。例如,如果我将大小增加到 10 个视图,则回收开始工作并且每次视图进入屏幕时都会调用 onBindViewHolder。
XML
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeRefresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<!-- RECYCLER VIEW -->
<android.support.v7.widget.RecyclerView
android:id="@+id/eventsList"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
Recycler 视图初始化
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
llm.setOrientation(LinearLayoutManager.VERTICAL);
eventsList.setLayoutManager(llm);
//Sets endless listener
scrollListener = new EndlessRecyclerOnScrollListener(llm,3,mLastDownloadedPage) {
@Override
public void onLoadMore(int current_page) {
Timber.d("Loading date for page: " + current_page);
mLastDownloadedPage = current_page;
//If it's showing cached don't download
if(showingCached)
return;
//Shows snackbar loading view
showSnackbarLoadingView();
//Gets events
getEvents(false);
}
};
//eventsList.addOnScrollListener(scrollListener);
//Set the adapter
mAdapter = new EventListAdapter(this,getActivity().getApplicationContext());
eventsList.setAdapter(mAdapter);
适配器
@Override
public EventHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
Timber.d("Create view holder pos: "+i);
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_events_row, viewGroup, false);
return new EventHolder(v,mListener);
}
@Override
public void onBindViewHolder(EventHolder eventHolder, int i) {
if(mBindListener != null)
mBindListener.onBind(eventHolder,i);
Timber.d("Bind view holder pos "+i);
Event event = eventList.get(i);
eventHolder.bindEvent(event);
//Sets the date
setDate(eventHolder.date, event);
//Sets the location
setLocation(eventHolder.distance,event);
}
在屏幕上只有 3 个可见视图,大小为 5,当我向下滚动时,我可以看到 createViewHolder
和 bindViewHolder
被调用用于位置 4 和 5,但是当我滚动到顶部时,退出屏幕时它们不会被回收。我可以确认,因为通过覆盖
@Override
public void onViewRecycled(EventHolder holder) {
super.onViewRecycled(holder);
Timber.d("onViewRecycled: "+holder.name);
}
没有记录任何消息。但是,如果视图计数增加,例如大小为 10,则一切正常,视图被回收并且每个位置都调用 onBindViewHolder
。
这是正常行为吗?如果是如何保存item view的状态,比如activated状态,我以前是把active位置保存在一个变量里,然后用bind方法进入screen时用这一行激活view
holder.itemView.setActivated(pos == lastSelectedPos);
这是正常行为,但您可以通过以下方式对其进行调整:
recyclerView.setItemViewCacheSize(int);
关于问题的第二部分 - 你是对的!将 "activated" 位置存储为适配器中的变量。在 onBindViewHolder() 中做类似的事情:
holder.itemView.setActivated(holder.getAdapterPosition() == lastSelectedPos);