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

        }




  • 2021-01-08 16:54:08

    如何在 Node.js 中使用 import / export 的三种方法

    注:第1、2种方法均是借助 babel,需要注意的是文章使用的babel版本 < 7。从 babel 7.X 版本开始,部分包名、用法发生了些许变化,大体与7之前的用法类似,详细请到官方手册学习 7.X 版本的改动(Babel 踩坑总结(三) —— 7.X 版本升级是我对 7.X 版本三大改动的总结)

  • 2021-01-10 17:19:00

    libc++_shared是什么冲突

    NDK 支持多种 C++ 运行时库。本文档介绍了这些库的相关信息、所涉及的折衷做法以及库的使用方法。

  • 2021-01-10 17:20:52

    NDK--CMakeLists配置第三方so库

    当我们创建一个NDK工程时,会自动创建一个CMakeLists.txt的文件,在AS中c++的编译器是使用LLVM,规则为cmake,今天来学习下cmake的基本套路 首先,我创建了两个NDK工程,第一个工程为lib,为第二个工程提供so库

  • 2021-01-12 10:56:09

    NodeJS封装mongodb

    NodeJS操作 Mongodb 并且对 Mongodb 类库进行封装