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

        }




  • 2020-01-20 08:29:14

    js如何生成唯一标识符UUID

    在JavaScript中生成uuid的代码如下,这个函数会直接给你返回uuid,所以直接调用,然后用变量接收即可!

  • 2020-01-30 11:19:58

    Android中添加两个(多个)FileProvider节点问题

    我们知道在android7.0,修改了对私有存储的限制,导致在获取资源的时候,不能通过Uri.fromFile(..)来获取uri了,但是在写入数据的时候是可以通过Uri.fromFile(..)来获取uri的,android 官网给出的解决办法是通过FileProvider来解决这一问题,我们需要在AndroidManifest.xml 配制provider节点。

  • 2020-02-02 15:40:36

    Apache Commons IO之IOUtils优雅操作流

    在开发过程中,你肯定遇到过从流中解析数据,或者把数据写入流中,或者输入流转换为输出流,而且最后还要进行流的关闭,原始jdk自带的方法写起来太复杂,还要注意各种异常,如果你为此感到烦恼,那IOUtils可以让我们优雅的操作流。

  • 2020-02-02 19:24:38

    百度视频SDK,突然不能播放

    开发过程中,不知道什么时候开始视频不能播发了,怎么办都不行,其他项目没问题,线上都也没有问题,这可急躁完蛋我了,整了仨小时,还是那熊样。 哎。

  • 2020-02-04 18:43:10

    AssetManager.finalize() Timed Out 解决办法以及分析

    在我们的项目崩溃中,有一个比较常见的bug,就是 java.util.concurrent.TimeoutException android.content.res.AssetManager.finalize() timed out after 10 seconds 意思简单明了,就是说在AssetManager析构的时候发生了超时异常。