【问题标题】:RecyclerView does not Recycling Views when use it inside NestedScrollViewRecyclerView 在 NestedScrollView 中使用时不会回收视图
【发布时间】:2016-10-02 02:52:08
【问题描述】:

我在NestedScrollView 中使用RecyclerView。我也将setNestedScrollingEnabled 设置为 false 为recyclerview

支持较低的API

ViewCompat.setNestedScrollingEnabled(mRecyclerView, false);

现在!当用户滚动视图时,一切似乎都还好,但是!!! recyclerview 中的视图不会被回收!!!并且堆大小迅速增长!

更新: RecyclerView 布局管理器是StaggeredLayoutManager

fragment_profile.xml

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

        <android.support.design.widget.AppBarLayout
            android:id="@+id/appbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" >
        </android.support.design.widget.AppBarLayout>

        <android.support.v4.widget.SwipeRefreshLayout
            android:id="@+id/profileSwipeRefreshLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >

                <!-- RecyclerView and NestedScrollView -->
                <include layout="@layout/fragment_profile_details" />

        </android.support.v4.widget.SwipeRefreshLayout>

</android.support.design.widget.CoordinatorLayout>

fragment_profile_details.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/rootLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    android:orientation="vertical" >

        <android.support.v4.widget.NestedScrollView
            android:id="@+id/nested_scrollbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="fill_vertical"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            android:fillViewport="true"
            android:scrollbars="none" >

                <LinearLayout
                    android:id="@+id/nested_scrollbar_linear"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:descendantFocusability="blocksDescendants"
                    android:orientation="vertical" >

                        <android.support.v7.widget.CardView
                            android:id="@+id/profileCardview"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            app:cardBackgroundColor="@color/card_backgroind"
                            app:cardCornerRadius="0dp"
                            app:cardElevation="0dp" >

                            <!-- Profile related stuff like avatar and etc. --->

                        </android.support.v7.widget.CardView>

                        <android.support.v7.widget.RecyclerView
                            android:id="@+id/list_view"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:layout_marginBottom="@dimen/four"
                            android:layout_marginEnd="@dimen/four"
                            android:layout_marginLeft="@dimen/four"
                            android:layout_marginRight="@dimen/four"
                            android:layout_marginStart="@dimen/four"
                            android:layout_marginTop="@dimen/four"
                            app:layout_behavior="@string/appbar_scrolling_view_behavior"
                            android:clipToPadding="false" />

                </LinearLayout>
        </android.support.v4.widget.NestedScrollView>
</LinearLayout>

ProfileFragment.java

mAdapter        = new MainAdapter(getActivity(), glide, Data);

listView        = (RecyclerView) view.findViewById(R.id.list_view);

ViewCompat.setNestedScrollingEnabled(listView, false);  
listView.setAdapter(mAdapter);

mStaggeredLM    = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mStaggeredLM.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);

listView.setLayoutManager(mStaggeredLM);

mScroll.setOnScrollChangeListener(new OnScrollChangeListener() {

        @Override
        public void onScrollChange(NestedScrollView arg0, int arg1, int arg2, int arg3, int arg4) {

            View view   = (View) mScroll.getChildAt(mScroll.getChildCount() - 1);
            int diff    = (view.getBottom() - ( mScroll.getHeight() + mScroll.getScrollY()));

            if(diff == 0){

                int visibleItemCount            = mStaggeredLM.getChildCount();
                int totalItemCount              = mStaggeredLM.getItemCount();

                int[] lastVisibleItemPositions  = mStaggeredLM.findLastVisibleItemPositions(null);
                int lastVisibleItemPos  = getLastVisibleItem(lastVisibleItemPositions);

                Log.e("getChildCount", String.valueOf(visibleItemCount));
                Log.e("getItemCount", String.valueOf(totalItemCount));
                Log.e("lastVisibleItemPos", String.valueOf(lastVisibleItemPos));

                if ((visibleItemCount + 5) >= totalItemCount) {

                    mLoadMore.setVisibility(View.VISIBLE);
                    Log.e("LOG", "Last Item Reached!");
                }

                mMore = true;
                mFresh = false;
                mRefresh = false;
                getPosts();
            }

        }

    });

P.s : 我已经为滚动视图设置了更多加载,因为recyclerview 连续执行并且无法停止!

感谢任何帮助

【问题讨论】:

  • 你能解释一下为什么在NestedScrollView里面加RecyclerView吗?
  • @MAY3AM 更新您的代码和 xml
  • NestedScrollView 绘制所有子元素,因此如果RecyclerView 已在NestedScrollView 内部使用,则适配器的所有元素将在第一次自己加载。更好的方法是仅使用RecyclerView 并使用getItmeViewTypeadapter 中返回cardView if(position==0)。正如 Rehan 所建议的那样。
  • 我通常选择@Pr38y。您面临什么性能问题?

标签: android android-recyclerview nestedscrollview recycle


【解决方案1】:

这是因为我们有一个回收器视图,它在滚动视图中具有滚动行为。 (在卷轴内滚动)

我认为解决此问题的最佳方法是将您的 profileCardview 作为回收站视图中的标题,然后删除嵌套的滚动视图。

如果它是一个列表视图,那么它就像 listView.addHeaderView(profileCardView) 一样简单,但是对于 Recycler 视图,没有 addheadview 等效项。因此,您可以参考以下链接来更改您的实现。

Is there an addHeaderView equivalent for RecyclerView?

【讨论】:

    【解决方案2】:

    对于 RecyclerView 或 ListView,高度应该是恒定的,因为如果它的大小不是恒定的,那么它将如何管理内存中可见行的最大数量。尝试更改 RecyclerView 属性 android:layout_height="match_parent" 或固定高度(例如 "300dp" - 根据需要),而不是 "wrap_content"。它应该会改善您的内存管理。

    【讨论】:

    • @CliveJefferies 将 layout_height 设置为固定大小将减少子视图更新时的重新绘制。您的意思是“别担心 - 如果我的子视图发生更改,则无需重新绘制此视图,因为它具有固定大小”。从理论上讲,您可以说它可能会减少内存占用,但主要是它会消除 UI 阻塞垃圾收集,从而使您的应用程序更流畅。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 2015-11-29
    • 2015-08-29
    • 1970-01-01
    • 1970-01-01
    • 2021-01-01
    相关资源
    最近更新 更多