关于RecyclerView的setHasFixedSize方法

recyclerView.setHasFixedSize方法什么时候设置为true 什么时候设置为false呢?

可以看下源码中关于这个方法的解释:

typescript 复制代码
 /**
     * RecyclerView can perform several optimizations if it can know in advance that RecyclerView's
     * size is not affected by the adapter contents. RecyclerView can still change its size based
     * on other factors (e.g. its parent's size) but this size calculation cannot depend on the
     * size of its children or contents of its adapter (except the number of items in the adapter).
     * <p>
     * If your use of RecyclerView falls into this category, set this to {@code true}. It will allow
     * RecyclerView to avoid invalidating the whole layout when its adapter contents change.
     *
     * @param hasFixedSize true if adapter changes cannot affect the size of the RecyclerView.
     */
    public void setHasFixedSize(boolean hasFixedSize) {
        mHasFixedSize = hasFixedSize;
    }

看上面的英文注释可以知道:

如果可以提前知道RecyclerView的大小不受adapter内容的影响,那么可以做一些优化。RecyclerView可以因为一些其他的因素(比如它父布局的大小)改变它自身的大小,但是不依赖于它的子布局或者adapter内容的大小。

如果使用RecyclerView属于上面所属的类别,那么可以设置为true。这将会允许RecyclerView当adapter内容改变时避免刷新整个布局。

在以前的RecycleView的源码中是这样的:

scss 复制代码
void onItemsInsertedOrRemoved() {
   if (hasFixedSize) layoutChildren();
   else requestLayout();
}

现在RecyclerView的源码中是这样的:

ini 复制代码
 @Override
    protected void onMeasure(int widthSpec, int heightSpec) {
        if (mLayout == null) {
            defaultOnMeasure(widthSpec, heightSpec);
            return;
        }
        if (mLayout.isAutoMeasureEnabled()) {
          ....... 省略部分代码
        } else {
            if (mHasFixedSize) {
                mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec);
                return;
            }
            // custom onMeasure
            ......  省略部分代码

                setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight());
                return;
            }

            if (mAdapter != null) {
                mState.mItemCount = mAdapter.getItemCount();
            } else {
                mState.mItemCount = 0;
            }
            startInterceptRequestLayout();
            mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec);
            stopInterceptRequestLayout(false);
            mState.mInPreLayout = false; // clear
        }
    }

由上面内容可知:

setHasFixedSize 为 true,是为了更改 adapter的内容不会改变 它的View的高度和宽度,那么就可以设置为 true来避免不必要的 requestLayout

简单的说:

(1)如果我们使用固定的宽度/高度:

ini 复制代码
<android.support.v7.widget.RecyclerView
    android:id="@+id/my_recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

可以用setHasFixedSize(true)

(2)如果我们不使用固定的宽度/高度:

ini 复制代码
<android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

应该使用setHasFixedSize(false),因为宽度或高度可以改变我们的大小。

总之,当布局文件高度或宽度设置为固定值或者 match_parent时 ,可以设置 setHasFixedSize =true。

相关推荐
ace望世界4 小时前
android的Parcelable
android
顾林海4 小时前
Android编译插桩之AspectJ:让代码像特工一样悄悄干活
android·面试·性能优化
叽哥4 小时前
Flutter Riverpod上手指南
android·flutter·ios
循环不息优化不止4 小时前
安卓开发设计模式全解析
android
诺诺Okami4 小时前
Android Framework-WMS-层级结构树
android
alexhilton15 小时前
面向开发者的系统设计:像建筑师一样思考
android·kotlin·android jetpack
CYRUS_STUDIO1 天前
用 Frida 控制 Android 线程:kill 命令、挂起与恢复全解析
android·linux·逆向
CYRUS_STUDIO1 天前
Frida 实战:Android JNI 数组 (jobjectArray) 操作全流程解析
android·逆向
用户091 天前
Gradle Cache Entries 深度探索
android·java·kotlin
循环不息优化不止1 天前
安卓 View 绘制机制深度解析
android