RecyclerView setHasFixedSize(true)的意义

2019-05-21 12:35:54

参考地址 RecyclerView setHasFixedSize(true)的意义


    /**

     * 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;

    }

注释说当知道Adapter内Item的改变不会影响RecyclerView宽高的时候,可以设置为true让RecyclerView避免重新计算大小。


设置为true,再调用notifyDataSetChanged(),发现大小重新计算了,看来理解出现错误了。还是再看一下哪些地方用到这个mHasFixedSize吧。




首先是onMeasure里用到,这个和自定义LayoutManager相关,先不管它。


剩下的就是triggerUpdateProcessor()方法了:


   void triggerUpdateProcessor() {

            if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) {

                ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable);

            } else {

                mAdapterUpdateDuringMeasure = true;

                requestLayout();

            }

        }


看一下triggerUpdateProcessor方法被哪些调用

onItemRangeChanged(),


onItemRangeInserted(),


onItemRangeRemoved(),


onItemRangeMoved()


这样看就很明白了,当调用Adapter的增删改插方法,最后就会根据mHasFixedSize这个值来判断需要不需要requestLayout();


再来看一下notifyDataSetChanged()执行的代码,最后是调用了onChanged,调用了requestLayout(),会去重新测量宽高。



        @Override

        public void onChanged() {

            assertNotInLayoutOrScroll(null);

            mState.mStructureChanged = true;

 

            setDataSetChangedAfterLayout();

            if (!mAdapterHelper.hasPendingUpdates()) {

                requestLayout();

            }

        }


总结:当我们确定Item的改变不会影响RecyclerView的宽高的时候可以设置setHasFixedSize(true),并通过Adapter的增删改插方法去刷新RecyclerView,而不是通过notifyDataSetChanged()。(其实可以直接设置为true,当需要改变宽高的时候就用notifyDataSetChanged()去整体刷新一下)


        public final void notifyItemChanged(int position) {

            mObservable.notifyItemRangeChanged(position, 1);

        }

 

        public final void notifyItemChanged(int position, Object payload) {

            mObservable.notifyItemRangeChanged(position, 1, payload);

        }

 

        public final void notifyItemRangeChanged(int positionStart, int itemCount) {

            mObservable.notifyItemRangeChanged(positionStart, itemCount);

        }

 

        public final void notifyItemRangeChanged(int positionStart, int itemCount, Object payload) {

            mObservable.notifyItemRangeChanged(positionStart, itemCount, payload);

        }

 

        

        public final void notifyItemInserted(int position) {

            mObservable.notifyItemRangeInserted(position, 1);

        }

 

        

        public final void notifyItemMoved(int fromPosition, int toPosition) {

            mObservable.notifyItemMoved(fromPosition, toPosition);

        }

 

        public final void notifyItemRangeInserted(int positionStart, int itemCount) {

            mObservable.notifyItemRangeInserted(positionStart, itemCount);

        }

 

        public final void notifyItemRemoved(int position) {

            mObservable.notifyItemRangeRemoved(position, 1);

        }

 

        public final void notifyItemRangeRemoved(int positionStart, int itemCount) {

            mObservable.notifyItemRangeRemoved(positionStart, itemCount);

        }




  • 2019-08-28 08:28:36

    Js apply,call方法详解,及其apply()方法的妙用

    在给对象参数的情况下,如果参数的形式是数组的时候,比如apply示例里面传递了参数arguments,这个参数是数组类型,并且在调用Person的时候参数的列表是对应一致的(也就是Person和Student的参数列表前两位是一致的) 就可以采用 apply , 如果我的Person的参数列表是这样的(age,name),而Student的参数列表是(name,age,grade),这样就可以用call来实现了,也就是直接指定参数列表对应值的位置(Person.call(this,age,name,grade));

  • 2019-08-28 08:49:47

    Nginx + fastcgi + php 的原理与关系

    CGI对每个请求会parse一遍对应脚本的配置文件(如php.ini), 加载配置和扩展,初始化执行环境,性能非常差,所有有了下面的流程:

  • 2019-08-28 09:23:15

    php单例模式

    单例模式,是一种常见的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。

  • 2019-08-28 22:45:02

    彻底搞懂Gradle、Gradle Wrapper与Android Plugin for Gradle的区别和联系

    Gradle是个构建系统,能够简化你的编译、打包、测试过程。熟悉Java的同学,可以把Gradle类比成Maven。Gradle Wrapper的作用是简化Gradle本身的安装、部署。不同版本的项目可能需要不同版本的Gradle,手工部署的话比较麻烦,而且可能产生冲突,所以需要Gradle Wrapper帮你搞定这些事情。Gradle Wrapper是Gradle项目的一部分。

  • 2019-08-30 21:53:51

    OpenSSL实践-Android下的编译和使用

    openssl可以编译成ARM下面的二进制代码(动态库或者静态库),方便APP使用,APP在使用的时候,需要使用JNI来进行调用。