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

相关推荐
JasonYin~26 分钟前
HarmonyOS NEXT 实战之元服务:静态案例效果---手机查看电量
android·华为·harmonyos
zhangphil35 分钟前
Android adb查看某个进程的总线程数
android·adb
抛空1 小时前
Android14 - SystemServer进程的启动与工作流程分析
android
Gerry_Liang3 小时前
记一次 Android 高内存排查
android·性能优化·内存泄露·mat
天天打码4 小时前
ThinkPHP项目如何关闭runtime下Log日志文件记录
android·java·javascript
爱数学的程序猿7 小时前
Python入门:6.深入解析Python中的序列
android·服务器·python
brhhh_sehe7 小时前
重生之我在异世界学编程之C语言:深入文件操作篇(下)
android·c语言·网络
zhangphil7 小时前
Android基于Path的addRoundRect,Canvas剪切clipPath简洁的圆形图实现,Kotlin(2)
android·kotlin
Calvin8808288 小时前
Android Studio 的革命性更新:Project Quartz 和 Gemini,开启 AI 开发新时代!
android·人工智能·android studio
敲代码敲到头发茂密9 小时前
【大语言模型】LangChain 核心模块介绍(Memorys)
android·语言模型·langchain