【问题标题】:RecyclerView not recycling views if the view count is small如果视图计数很小,RecyclerView 不会回收视图
【发布时间】:2015-11-29 04:39:36
【问题描述】:

我一直在处理 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>

回收站视图初始化

    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,当我向下滚动时,我可以看到位置 4 和 5 调用了 createViewHolderbindViewHolder,但是当我滚动到顶部时,它们退出屏幕时不回收。我可以确认,因为通过覆盖

@Override
public void onViewRecycled(EventHolder holder) {
    super.onViewRecycled(holder);
    Timber.d("onViewRecycled: "+holder.name);
}

没有消息被记录。但是,如果视图计数增加,例如大小为 10,则一切正常,视图被回收,并且每个位置都调用 onBindViewHolder

这是正常行为吗?如果是我如何保存项目视图的状态,例如激活状态,我曾经将活动位置保存在变量中,然后使用此行在视图进入屏幕时使用绑定方法激活视图

        holder.itemView.setActivated(pos == lastSelectedPos);

【问题讨论】:

    标签: android android-recyclerview


    【解决方案1】:

    这是正常行为,但您可以通过以下方式对其进行调整:

    recyclerView.setItemViewCacheSize(int);
    

    关于问题的第二部分 - 你是对的!将“激活”位置作为变量存储在适配器中。在 onBindViewHolder() 中执行以下操作:

    holder.itemView.setActivated(holder.getAdapterPosition() == lastSelectedPos);
    

    【讨论】:

    • 顺便提一下,当我在recyclerView.setItemViewCacheSize()里面挖掘时,缓存的默认值是2
    • 谢谢你 kirtan403 我一直在到处寻找。
    • 救命稻草!只需设置 recyclerView.setItemViewCacheSize(-1);它就像一个魅力!非常感谢。注意:当设置recyclerView.setItemViewCacheSize(0);第一项给我带来了一些麻烦,因此将其更改为 -1 并解决了问题
    猜你喜欢
    • 2016-10-02
    • 1970-01-01
    • 1970-01-01
    • 2015-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-22
    • 2018-01-10
    相关资源
    最近更新 更多