关于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。

相关推荐
不吃凉粉2 小时前
Android Studio USB串口通信
android·ide·android studio
zhangphil2 小时前
android studio设置大内存,提升编译速度
android·android studio
编程乐学3 小时前
安卓非原创--基于Android Studio 实现的天气预报App
android·ide·android studio·课程设计·大作业·天气预报·安卓大作业
大熊的瓜地5 小时前
Android automotive 框架
android·android car
私人珍藏库6 小时前
[Android] Alarm Clock Pro 11.1.0一款经典简约个性的时钟
android·时钟
消失的旧时光-19438 小时前
ScheduledExecutorService
android·java·开发语言
小糖学代码8 小时前
MySQL:14.mysql connect
android·数据库·mysql·adb
怪兽201410 小时前
请谈谈什么是同步屏障?
android·面试
帅锅锅00711 小时前
SeLinux 全面详解
android·linux
只想搞钱的肥仔11 小时前
Android thermal (5)_cooling device(下)
android