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

相关推荐
j***57682 分钟前
MySQL——表操作及查询
android·mysql·adb
轻口味13 分钟前
基于Rokid Glasses的AI助盲应用实践:让科技点亮视障者的世界
android
j***894640 分钟前
MySQL数据的增删改查(一)
android·javascript·mysql
小画家~1 小时前
第三十四:golang 原生 pgsql 对应操作
android·开发语言·golang
r***18641 小时前
FlinkCDC实战:将 MySQL 数据同步至 ES
android·mysql·elasticsearch
p***62991 小时前
mysql-connector-java 和 mysql-connector-j的区别
android·java·mysql
海天鹰1 小时前
ACTION_PICK与ACTION_GET_CONTENT的区别
android
i***68322 小时前
图文详述:MySQL的下载、安装、配置、使用
android·mysql·adb
6***v4172 小时前
MySQL 时区参数 time_zone 详解
android·mysql·adb
王能2 小时前
Android三阶贝塞尔曲线应用——根据指定点画出完美的贝塞尔
android·贝塞尔曲线·图表·顶点