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-14 06:15:04

    通过glide获取图片显示后的真正宽高

    有时候需要获取网络图片的宽高来设置图片显示的大小,很多人会直接利用Glide的加载监听去拿图片的宽高,但是这样拿到的不是图片真正的宽高,而是图片显示在ImageView后的宽高。如下:

  • 2021-01-14 09:38:57

    Chrome插件详细教程

    严格来讲,我们正在说的东西应该叫Chrome扩展(Chrome Extension),真正意义上的Chrome插件是更底层的浏览器功能扩展,可能需要对浏览器源码有一定掌握才有能力去开发。鉴于Chrome插件的叫法已经习惯,本文也全部采用这种叫法,但读者需深知本文所描述的Chrome插件实际上指的是Chrome扩展。

  • 2021-01-14 17:07:51

    chrome.contextMenus.create不出现菜单

    主要原因是,我每次刷新玩,都复制一下右键,然而并没有出现菜单,一度颓废啊,因为demo,还有其他人的文章都是这样的。 哎,后来发现是这样的,我缺少了contexts选项。其实我是成功了,我现在只要不选择文字,直接点右键,菜单已经出现了哦。

  • 2021-01-15 13:06:08

    监控 MongoDB -

    随着MongoDB中保存的数据越来越多,对MongoDB服务状态的监控也越来越重要,经常关注服务是否健康,才能防止故障以及优化。

  • 2021-01-15 13:30:21

    MongoDb web 用户界面

    MongoDB 的 Web 界面访问端口比服务的端口多1000。 如果你的MongoDB运行端口使用默认的27017,你可以在端口号为28017访问web用户界面,即地址为:http://localhost:28017。