Understanding RecyclerView setHasFixedSize












101















I'm having some trouble understanding setHasFixedSize(). I know that it is used for optimization when the size of RecyclerView doesn't change, from the docs.



What does that mean though? In most common cases a ListView almost always has a fixed size. In what cases would it not be a fixed size? Does it mean that the actual real estate that it occupies on screen grows with the content?










share|improve this question

























  • stackoverflow.com/a/40707099/1177959

    – Sotti
    Nov 20 '16 at 17:37











  • I found this answer is helpful and very easy to understand [StackOverflow - rv.setHasFixedSize(true); ](stackoverflow.com/questions/28827597/…)

    – Laura Taylor
    Jan 14 at 11:42
















101















I'm having some trouble understanding setHasFixedSize(). I know that it is used for optimization when the size of RecyclerView doesn't change, from the docs.



What does that mean though? In most common cases a ListView almost always has a fixed size. In what cases would it not be a fixed size? Does it mean that the actual real estate that it occupies on screen grows with the content?










share|improve this question

























  • stackoverflow.com/a/40707099/1177959

    – Sotti
    Nov 20 '16 at 17:37











  • I found this answer is helpful and very easy to understand [StackOverflow - rv.setHasFixedSize(true); ](stackoverflow.com/questions/28827597/…)

    – Laura Taylor
    Jan 14 at 11:42














101












101








101


29






I'm having some trouble understanding setHasFixedSize(). I know that it is used for optimization when the size of RecyclerView doesn't change, from the docs.



What does that mean though? In most common cases a ListView almost always has a fixed size. In what cases would it not be a fixed size? Does it mean that the actual real estate that it occupies on screen grows with the content?










share|improve this question
















I'm having some trouble understanding setHasFixedSize(). I know that it is used for optimization when the size of RecyclerView doesn't change, from the docs.



What does that mean though? In most common cases a ListView almost always has a fixed size. In what cases would it not be a fixed size? Does it mean that the actual real estate that it occupies on screen grows with the content?







android android-5.0-lollipop android-recyclerview






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 25 '15 at 1:20









Xaver Kapeller

38.8k107675




38.8k107675










asked Feb 25 '15 at 0:49









SIr CodealotSIr Codealot

2,10072843




2,10072843













  • stackoverflow.com/a/40707099/1177959

    – Sotti
    Nov 20 '16 at 17:37











  • I found this answer is helpful and very easy to understand [StackOverflow - rv.setHasFixedSize(true); ](stackoverflow.com/questions/28827597/…)

    – Laura Taylor
    Jan 14 at 11:42



















  • stackoverflow.com/a/40707099/1177959

    – Sotti
    Nov 20 '16 at 17:37











  • I found this answer is helpful and very easy to understand [StackOverflow - rv.setHasFixedSize(true); ](stackoverflow.com/questions/28827597/…)

    – Laura Taylor
    Jan 14 at 11:42

















stackoverflow.com/a/40707099/1177959

– Sotti
Nov 20 '16 at 17:37





stackoverflow.com/a/40707099/1177959

– Sotti
Nov 20 '16 at 17:37













I found this answer is helpful and very easy to understand [StackOverflow - rv.setHasFixedSize(true); ](stackoverflow.com/questions/28827597/…)

– Laura Taylor
Jan 14 at 11:42





I found this answer is helpful and very easy to understand [StackOverflow - rv.setHasFixedSize(true); ](stackoverflow.com/questions/28827597/…)

– Laura Taylor
Jan 14 at 11:42












7 Answers
7






active

oldest

votes


















79














A very simplified version of RecyclerView has:



void onItemsInsertedOrRemoved() {
if (hasFixedSize) layoutChildren();
else requestLayout();
}


This link describes why calling requestLayout might be expensive. Basically whenever items are inserted, moved or removed the size (width and height) of RecyclerView might change and in turn the size of any other view in view hierarchy might change. This is particularly troublesome if items are added or removed frequently.



Avoid unnecessary layout passes by setting setHasFixedSize to true when changing the contents of the adapter does not change it's height or the width.





Update: The JavaDoc has been updated to better describe what the method actually does.




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


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.







share|improve this answer





















  • 107





    RecyclerView size changes every time you add something no matter what. What setHasFixedSize does is that it makes sure (by user input) that this change of size of RecyclerView is constant. The height (or width) of the item won't change. Every item added or removed will be the same. If you dont set this it will check if the size of the item has changed and thats expensive. Just clarifying because this answer is confusing.

    – Arnold Balliu
    May 25 '16 at 18:42






  • 9





    @ArnoldB excellent clarification. I would even argue it as a standalone answer.

    – YoungCoconutCode
    Jun 17 '16 at 16:04











  • @ArnoldB - I am still confused. Are you suggesting that we should set hasFixedSize to true if the widths/heights of all children are constant ? If yes, what if there is a possibility that some children can be removed at runtime (I have a swipe to dismiss feature) - is it okay to set true ?

    – Jaguar
    Jun 30 '16 at 2:32











  • Yes. Because the width and height of the item is not changing. It is just being added or removed. Adding or removing items does not change their size.

    – Arnold Balliu
    Jun 30 '16 at 2:43






  • 1





    @ArnoldB I don't think the size(width/height) of the item is a problem here. It won't check the item's size either. It just tells the RecyclerView to call requestLayout or not after the dataSet has been updated.

    – Kimi Chiu
    Jan 2 '17 at 10:06



















17














Can confirm setHasFixedSize relates to the RecyclerView itself, and not the size of each item adapted to it.



You can now use android:layout_height="wrap_content" on a RecyclerView, which, among other things, allows a CollapsingToolbarLayout to know it should not collapse when the RecyclerView is empty. This only works when you use setHasFixedSize(false) on the RecylcerView.



If you use setHasFixedSize(true) on the RecyclerView, this behavior to prevent the CollapsingToolbarLayout from collapsing does not work, even though the RecyclerView is indeed empty.



If setHasFixedSize was related to the size of items, it shouldn't have any effect when the RecyclerView has no items.






share|improve this answer



















  • 3





    I've just had an experience that points to the same direction. Using a RecyclerView with a GridLayoutManager(3 items per row) and layout_height = wrap_content. When I click a button that adds 3 new items to the list, the recycler view does not expand to fit the new items. Rather, it maintains the same size, and the only way to see the new items is scrolling it. Even though the items have the same size, I had to remove setHasFixedSize(true) to make it expand when new items are added.

    – Mateus Gondim
    Oct 31 '16 at 19:49













  • I think you're right. From the document, hasFixedSize: set to true if adapter changes cannot affect the size of the RecyclerView. So even if the size of the item will change, you still can set this to true.

    – Kimi Chiu
    Jan 2 '17 at 9:38



















12














The ListView had a similar named function that I think did reflect info about the size of the individual list item heights. The documentation for RecyclerView pretty clearly states it is referring to the size of the RecyclerView itself, not the size of its items.



From the RecyclerView source comment above the setHasFixedSize() method:



 * RecyclerView can perform several optimizations if it can know in advance that changes in
* adapter content cannot change the size of the RecyclerView itself.
* If your use of RecyclerView falls into this category, set this to true.





share|improve this answer



















  • 13





    But how is RecyclerView's "size" defined? Is it the size visible on screen only, or the full size of the RecyclerView, which equals (sum of item heights + padding + spacing)?

    – Vicky Chijwani
    May 14 '15 at 18:37








  • 1





    Indeed, this needs more info. If you remove items and the recyclerview shrinks, is it considered that is had changed size?

    – Henrique de Sousa
    Jul 3 '15 at 17:53






  • 2





    I would think of it like how a TextView can lay itself out. If you specify wrap_content, then when you set text the TextView can request a layout pass and change the amount of space it occupies on the screen. If you specify match_parent or a fixed dimension, then TextView will not request a layout pass because the size is fixed and the amount of text insde will never change the amount of space occupied. RecyclerView is the same. setHasFixedSize() hints to RV it should never need to request layout passes based on changes to the adapter items.

    – dangVarmit
    Jul 6 '15 at 17:56













  • @dangVarmit nice explanation!

    – howerknea
    Jun 27 '16 at 8:55



















3














setHasFixedSize(true) means the RecyclerView has children (items) that has fixed width and height. This allows the RecyclerView to optimize better by figuring out the exact height and width of the entire list based on the your adapter.






share|improve this answer



















  • 4





    That's not what @dangVarmit has suggested.

    – strangetimes
    Jul 19 '16 at 0:14






  • 1





    Misleading, it's actually the Recycler view size, not the size of the content

    – Benoit
    Apr 16 '18 at 14:28



















2














Wen we set setHasFixedSize(true) on RecyclerView that means recycler's size is fixed and is not affected by the adapter contents. And in this case onLayout is not called on recycler when we update the adaptrer's data (but there is an exception).



Let's go to the example:



RecyclerView has a RecyclerViewDataObserver (find default implemntation in this file) with several methods, the main important is:



void triggerUpdateProcessor() {
if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) {
ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable);
} else {
mAdapterUpdateDuringMeasure = true;
requestLayout();
}
}


This method is called if we set setHasFixedSize(true) and update an adapter's data via: notifyItemRangeChanged, notifyItemRangeInserted, notifyItemRangeRemoved or notifyItemRangeMoved. In this case there is no calls to the recycler's onLayout, but there is calls to requestLayout for updating childs.



But if we set setHasFixedSize(true) and update an adapter's data via notifyItemChanged then there is call to onChange of the recycler's default RecyclerViewDataObserver and no calls to triggerUpdateProcessor. In this case the recycler onLayout is called whenever we set setHasFixedSize true or false.



// no calls to triggerUpdateProcessor
@Override
public void onChanged() {
assertNotInLayoutOrScroll(null);
mState.mStructureChanged = true;

processDataSetCompletelyChanged(true);
if (!mAdapterHelper.hasPendingUpdates()) {
requestLayout();
}
}

// calls to triggerUpdateProcessor
@Override
public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
assertNotInLayoutOrScroll(null);
if (mAdapterHelper.onItemRangeChanged(positionStart, itemCount, payload)) {
triggerUpdateProcessor();
}
}


How to check by yourself:



Create custom RecyclerView and override:



override fun requestLayout() {
Log.d("CustomRecycler", "requestLayout is called")
super.requestLayout()
}

override fun invalidate() {
Log.d("CustomRecycler", "invalidate is called")
super.invalidate()
}

override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
Log.d("CustomRecycler", "onLayout is called")
super.onLayout(changed, l, t, r, b)
}


Set the recycler size to match_parent (in xml). Try to update adapter's data using replaceData and replaceOne with seting setHasFixedSize(true) and then false.



// onLayout is called every time
fun replaceAll(data: List<String>) {
dataSet.clear()
dataSet.addAll(data)
this.notifyDataSetChanged()
}

// onLayout is called only for setHasFixedSize(false)
fun replaceOne(data: List<String>) {
dataSet.removeAt(0)
dataSet.addAll(0, data[0])
this.notifyItemChanged(0)
}


And check your log.



My log:



// for replaceAll
D/CustomRecycler: requestLayout is called
D/CustomRecycler: onMeasure is called
D/CustomRecycler: onMeasure is called
D/CustomRecycler: onLayout
D/CustomRecycler: requestLayout is called
D/CustomRecycler: requestLayout is called
D/CustomRecycler: onDraw is called

// for replaceOne
D/CustomRecycler: requestLayout is called
D/CustomRecycler: onDraw is called
D/CustomRecycler: requestLayout is called
D/CustomRecycler: onDraw is called


Summarize:



If we set setHasFixedSize(true) and update adapter's data with notifying an observer in some other way than calling notifyDataSetChanged, then you have some perfomance, because the is no calls to the recycler onLayout method.






share|improve this answer


























  • Did you tested with RecyclerView of height using wrap_content or match_parent ?

    – Lubos Mudrak
    Dec 14 '18 at 15:22



















0














It affects the animations of the recyclerview, if it's false.. the insert and remove animations won't show. so make sure it's true in case you added animation for the recyclerview.






share|improve this answer































    0














    If the size of the RecyclerView (the RecyclerView itself)



    ... does not depend on the adapter content:



    mRecyclerView.setHasFixedSize(true);


    ...depends on the adapter content:



    mRecyclerView.setHasFixedSize(false);





    share|improve this answer

























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f28709220%2funderstanding-recyclerview-sethasfixedsize%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      7 Answers
      7






      active

      oldest

      votes








      7 Answers
      7






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      79














      A very simplified version of RecyclerView has:



      void onItemsInsertedOrRemoved() {
      if (hasFixedSize) layoutChildren();
      else requestLayout();
      }


      This link describes why calling requestLayout might be expensive. Basically whenever items are inserted, moved or removed the size (width and height) of RecyclerView might change and in turn the size of any other view in view hierarchy might change. This is particularly troublesome if items are added or removed frequently.



      Avoid unnecessary layout passes by setting setHasFixedSize to true when changing the contents of the adapter does not change it's height or the width.





      Update: The JavaDoc has been updated to better describe what the method actually does.




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


      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.







      share|improve this answer





















      • 107





        RecyclerView size changes every time you add something no matter what. What setHasFixedSize does is that it makes sure (by user input) that this change of size of RecyclerView is constant. The height (or width) of the item won't change. Every item added or removed will be the same. If you dont set this it will check if the size of the item has changed and thats expensive. Just clarifying because this answer is confusing.

        – Arnold Balliu
        May 25 '16 at 18:42






      • 9





        @ArnoldB excellent clarification. I would even argue it as a standalone answer.

        – YoungCoconutCode
        Jun 17 '16 at 16:04











      • @ArnoldB - I am still confused. Are you suggesting that we should set hasFixedSize to true if the widths/heights of all children are constant ? If yes, what if there is a possibility that some children can be removed at runtime (I have a swipe to dismiss feature) - is it okay to set true ?

        – Jaguar
        Jun 30 '16 at 2:32











      • Yes. Because the width and height of the item is not changing. It is just being added or removed. Adding or removing items does not change their size.

        – Arnold Balliu
        Jun 30 '16 at 2:43






      • 1





        @ArnoldB I don't think the size(width/height) of the item is a problem here. It won't check the item's size either. It just tells the RecyclerView to call requestLayout or not after the dataSet has been updated.

        – Kimi Chiu
        Jan 2 '17 at 10:06
















      79














      A very simplified version of RecyclerView has:



      void onItemsInsertedOrRemoved() {
      if (hasFixedSize) layoutChildren();
      else requestLayout();
      }


      This link describes why calling requestLayout might be expensive. Basically whenever items are inserted, moved or removed the size (width and height) of RecyclerView might change and in turn the size of any other view in view hierarchy might change. This is particularly troublesome if items are added or removed frequently.



      Avoid unnecessary layout passes by setting setHasFixedSize to true when changing the contents of the adapter does not change it's height or the width.





      Update: The JavaDoc has been updated to better describe what the method actually does.




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


      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.







      share|improve this answer





















      • 107





        RecyclerView size changes every time you add something no matter what. What setHasFixedSize does is that it makes sure (by user input) that this change of size of RecyclerView is constant. The height (or width) of the item won't change. Every item added or removed will be the same. If you dont set this it will check if the size of the item has changed and thats expensive. Just clarifying because this answer is confusing.

        – Arnold Balliu
        May 25 '16 at 18:42






      • 9





        @ArnoldB excellent clarification. I would even argue it as a standalone answer.

        – YoungCoconutCode
        Jun 17 '16 at 16:04











      • @ArnoldB - I am still confused. Are you suggesting that we should set hasFixedSize to true if the widths/heights of all children are constant ? If yes, what if there is a possibility that some children can be removed at runtime (I have a swipe to dismiss feature) - is it okay to set true ?

        – Jaguar
        Jun 30 '16 at 2:32











      • Yes. Because the width and height of the item is not changing. It is just being added or removed. Adding or removing items does not change their size.

        – Arnold Balliu
        Jun 30 '16 at 2:43






      • 1





        @ArnoldB I don't think the size(width/height) of the item is a problem here. It won't check the item's size either. It just tells the RecyclerView to call requestLayout or not after the dataSet has been updated.

        – Kimi Chiu
        Jan 2 '17 at 10:06














      79












      79








      79







      A very simplified version of RecyclerView has:



      void onItemsInsertedOrRemoved() {
      if (hasFixedSize) layoutChildren();
      else requestLayout();
      }


      This link describes why calling requestLayout might be expensive. Basically whenever items are inserted, moved or removed the size (width and height) of RecyclerView might change and in turn the size of any other view in view hierarchy might change. This is particularly troublesome if items are added or removed frequently.



      Avoid unnecessary layout passes by setting setHasFixedSize to true when changing the contents of the adapter does not change it's height or the width.





      Update: The JavaDoc has been updated to better describe what the method actually does.




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


      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.







      share|improve this answer















      A very simplified version of RecyclerView has:



      void onItemsInsertedOrRemoved() {
      if (hasFixedSize) layoutChildren();
      else requestLayout();
      }


      This link describes why calling requestLayout might be expensive. Basically whenever items are inserted, moved or removed the size (width and height) of RecyclerView might change and in turn the size of any other view in view hierarchy might change. This is particularly troublesome if items are added or removed frequently.



      Avoid unnecessary layout passes by setting setHasFixedSize to true when changing the contents of the adapter does not change it's height or the width.





      Update: The JavaDoc has been updated to better describe what the method actually does.




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


      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.








      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Aug 13 '18 at 14:05

























      answered Oct 27 '15 at 10:22









      LukaCikoLukaCiko

      3,61912130




      3,61912130








      • 107





        RecyclerView size changes every time you add something no matter what. What setHasFixedSize does is that it makes sure (by user input) that this change of size of RecyclerView is constant. The height (or width) of the item won't change. Every item added or removed will be the same. If you dont set this it will check if the size of the item has changed and thats expensive. Just clarifying because this answer is confusing.

        – Arnold Balliu
        May 25 '16 at 18:42






      • 9





        @ArnoldB excellent clarification. I would even argue it as a standalone answer.

        – YoungCoconutCode
        Jun 17 '16 at 16:04











      • @ArnoldB - I am still confused. Are you suggesting that we should set hasFixedSize to true if the widths/heights of all children are constant ? If yes, what if there is a possibility that some children can be removed at runtime (I have a swipe to dismiss feature) - is it okay to set true ?

        – Jaguar
        Jun 30 '16 at 2:32











      • Yes. Because the width and height of the item is not changing. It is just being added or removed. Adding or removing items does not change their size.

        – Arnold Balliu
        Jun 30 '16 at 2:43






      • 1





        @ArnoldB I don't think the size(width/height) of the item is a problem here. It won't check the item's size either. It just tells the RecyclerView to call requestLayout or not after the dataSet has been updated.

        – Kimi Chiu
        Jan 2 '17 at 10:06














      • 107





        RecyclerView size changes every time you add something no matter what. What setHasFixedSize does is that it makes sure (by user input) that this change of size of RecyclerView is constant. The height (or width) of the item won't change. Every item added or removed will be the same. If you dont set this it will check if the size of the item has changed and thats expensive. Just clarifying because this answer is confusing.

        – Arnold Balliu
        May 25 '16 at 18:42






      • 9





        @ArnoldB excellent clarification. I would even argue it as a standalone answer.

        – YoungCoconutCode
        Jun 17 '16 at 16:04











      • @ArnoldB - I am still confused. Are you suggesting that we should set hasFixedSize to true if the widths/heights of all children are constant ? If yes, what if there is a possibility that some children can be removed at runtime (I have a swipe to dismiss feature) - is it okay to set true ?

        – Jaguar
        Jun 30 '16 at 2:32











      • Yes. Because the width and height of the item is not changing. It is just being added or removed. Adding or removing items does not change their size.

        – Arnold Balliu
        Jun 30 '16 at 2:43






      • 1





        @ArnoldB I don't think the size(width/height) of the item is a problem here. It won't check the item's size either. It just tells the RecyclerView to call requestLayout or not after the dataSet has been updated.

        – Kimi Chiu
        Jan 2 '17 at 10:06








      107




      107





      RecyclerView size changes every time you add something no matter what. What setHasFixedSize does is that it makes sure (by user input) that this change of size of RecyclerView is constant. The height (or width) of the item won't change. Every item added or removed will be the same. If you dont set this it will check if the size of the item has changed and thats expensive. Just clarifying because this answer is confusing.

      – Arnold Balliu
      May 25 '16 at 18:42





      RecyclerView size changes every time you add something no matter what. What setHasFixedSize does is that it makes sure (by user input) that this change of size of RecyclerView is constant. The height (or width) of the item won't change. Every item added or removed will be the same. If you dont set this it will check if the size of the item has changed and thats expensive. Just clarifying because this answer is confusing.

      – Arnold Balliu
      May 25 '16 at 18:42




      9




      9





      @ArnoldB excellent clarification. I would even argue it as a standalone answer.

      – YoungCoconutCode
      Jun 17 '16 at 16:04





      @ArnoldB excellent clarification. I would even argue it as a standalone answer.

      – YoungCoconutCode
      Jun 17 '16 at 16:04













      @ArnoldB - I am still confused. Are you suggesting that we should set hasFixedSize to true if the widths/heights of all children are constant ? If yes, what if there is a possibility that some children can be removed at runtime (I have a swipe to dismiss feature) - is it okay to set true ?

      – Jaguar
      Jun 30 '16 at 2:32





      @ArnoldB - I am still confused. Are you suggesting that we should set hasFixedSize to true if the widths/heights of all children are constant ? If yes, what if there is a possibility that some children can be removed at runtime (I have a swipe to dismiss feature) - is it okay to set true ?

      – Jaguar
      Jun 30 '16 at 2:32













      Yes. Because the width and height of the item is not changing. It is just being added or removed. Adding or removing items does not change their size.

      – Arnold Balliu
      Jun 30 '16 at 2:43





      Yes. Because the width and height of the item is not changing. It is just being added or removed. Adding or removing items does not change their size.

      – Arnold Balliu
      Jun 30 '16 at 2:43




      1




      1





      @ArnoldB I don't think the size(width/height) of the item is a problem here. It won't check the item's size either. It just tells the RecyclerView to call requestLayout or not after the dataSet has been updated.

      – Kimi Chiu
      Jan 2 '17 at 10:06





      @ArnoldB I don't think the size(width/height) of the item is a problem here. It won't check the item's size either. It just tells the RecyclerView to call requestLayout or not after the dataSet has been updated.

      – Kimi Chiu
      Jan 2 '17 at 10:06













      17














      Can confirm setHasFixedSize relates to the RecyclerView itself, and not the size of each item adapted to it.



      You can now use android:layout_height="wrap_content" on a RecyclerView, which, among other things, allows a CollapsingToolbarLayout to know it should not collapse when the RecyclerView is empty. This only works when you use setHasFixedSize(false) on the RecylcerView.



      If you use setHasFixedSize(true) on the RecyclerView, this behavior to prevent the CollapsingToolbarLayout from collapsing does not work, even though the RecyclerView is indeed empty.



      If setHasFixedSize was related to the size of items, it shouldn't have any effect when the RecyclerView has no items.






      share|improve this answer



















      • 3





        I've just had an experience that points to the same direction. Using a RecyclerView with a GridLayoutManager(3 items per row) and layout_height = wrap_content. When I click a button that adds 3 new items to the list, the recycler view does not expand to fit the new items. Rather, it maintains the same size, and the only way to see the new items is scrolling it. Even though the items have the same size, I had to remove setHasFixedSize(true) to make it expand when new items are added.

        – Mateus Gondim
        Oct 31 '16 at 19:49













      • I think you're right. From the document, hasFixedSize: set to true if adapter changes cannot affect the size of the RecyclerView. So even if the size of the item will change, you still can set this to true.

        – Kimi Chiu
        Jan 2 '17 at 9:38
















      17














      Can confirm setHasFixedSize relates to the RecyclerView itself, and not the size of each item adapted to it.



      You can now use android:layout_height="wrap_content" on a RecyclerView, which, among other things, allows a CollapsingToolbarLayout to know it should not collapse when the RecyclerView is empty. This only works when you use setHasFixedSize(false) on the RecylcerView.



      If you use setHasFixedSize(true) on the RecyclerView, this behavior to prevent the CollapsingToolbarLayout from collapsing does not work, even though the RecyclerView is indeed empty.



      If setHasFixedSize was related to the size of items, it shouldn't have any effect when the RecyclerView has no items.






      share|improve this answer



















      • 3





        I've just had an experience that points to the same direction. Using a RecyclerView with a GridLayoutManager(3 items per row) and layout_height = wrap_content. When I click a button that adds 3 new items to the list, the recycler view does not expand to fit the new items. Rather, it maintains the same size, and the only way to see the new items is scrolling it. Even though the items have the same size, I had to remove setHasFixedSize(true) to make it expand when new items are added.

        – Mateus Gondim
        Oct 31 '16 at 19:49













      • I think you're right. From the document, hasFixedSize: set to true if adapter changes cannot affect the size of the RecyclerView. So even if the size of the item will change, you still can set this to true.

        – Kimi Chiu
        Jan 2 '17 at 9:38














      17












      17








      17







      Can confirm setHasFixedSize relates to the RecyclerView itself, and not the size of each item adapted to it.



      You can now use android:layout_height="wrap_content" on a RecyclerView, which, among other things, allows a CollapsingToolbarLayout to know it should not collapse when the RecyclerView is empty. This only works when you use setHasFixedSize(false) on the RecylcerView.



      If you use setHasFixedSize(true) on the RecyclerView, this behavior to prevent the CollapsingToolbarLayout from collapsing does not work, even though the RecyclerView is indeed empty.



      If setHasFixedSize was related to the size of items, it shouldn't have any effect when the RecyclerView has no items.






      share|improve this answer













      Can confirm setHasFixedSize relates to the RecyclerView itself, and not the size of each item adapted to it.



      You can now use android:layout_height="wrap_content" on a RecyclerView, which, among other things, allows a CollapsingToolbarLayout to know it should not collapse when the RecyclerView is empty. This only works when you use setHasFixedSize(false) on the RecylcerView.



      If you use setHasFixedSize(true) on the RecyclerView, this behavior to prevent the CollapsingToolbarLayout from collapsing does not work, even though the RecyclerView is indeed empty.



      If setHasFixedSize was related to the size of items, it shouldn't have any effect when the RecyclerView has no items.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Sep 28 '16 at 0:48









      KevinKevin

      1,1641220




      1,1641220








      • 3





        I've just had an experience that points to the same direction. Using a RecyclerView with a GridLayoutManager(3 items per row) and layout_height = wrap_content. When I click a button that adds 3 new items to the list, the recycler view does not expand to fit the new items. Rather, it maintains the same size, and the only way to see the new items is scrolling it. Even though the items have the same size, I had to remove setHasFixedSize(true) to make it expand when new items are added.

        – Mateus Gondim
        Oct 31 '16 at 19:49













      • I think you're right. From the document, hasFixedSize: set to true if adapter changes cannot affect the size of the RecyclerView. So even if the size of the item will change, you still can set this to true.

        – Kimi Chiu
        Jan 2 '17 at 9:38














      • 3





        I've just had an experience that points to the same direction. Using a RecyclerView with a GridLayoutManager(3 items per row) and layout_height = wrap_content. When I click a button that adds 3 new items to the list, the recycler view does not expand to fit the new items. Rather, it maintains the same size, and the only way to see the new items is scrolling it. Even though the items have the same size, I had to remove setHasFixedSize(true) to make it expand when new items are added.

        – Mateus Gondim
        Oct 31 '16 at 19:49













      • I think you're right. From the document, hasFixedSize: set to true if adapter changes cannot affect the size of the RecyclerView. So even if the size of the item will change, you still can set this to true.

        – Kimi Chiu
        Jan 2 '17 at 9:38








      3




      3





      I've just had an experience that points to the same direction. Using a RecyclerView with a GridLayoutManager(3 items per row) and layout_height = wrap_content. When I click a button that adds 3 new items to the list, the recycler view does not expand to fit the new items. Rather, it maintains the same size, and the only way to see the new items is scrolling it. Even though the items have the same size, I had to remove setHasFixedSize(true) to make it expand when new items are added.

      – Mateus Gondim
      Oct 31 '16 at 19:49







      I've just had an experience that points to the same direction. Using a RecyclerView with a GridLayoutManager(3 items per row) and layout_height = wrap_content. When I click a button that adds 3 new items to the list, the recycler view does not expand to fit the new items. Rather, it maintains the same size, and the only way to see the new items is scrolling it. Even though the items have the same size, I had to remove setHasFixedSize(true) to make it expand when new items are added.

      – Mateus Gondim
      Oct 31 '16 at 19:49















      I think you're right. From the document, hasFixedSize: set to true if adapter changes cannot affect the size of the RecyclerView. So even if the size of the item will change, you still can set this to true.

      – Kimi Chiu
      Jan 2 '17 at 9:38





      I think you're right. From the document, hasFixedSize: set to true if adapter changes cannot affect the size of the RecyclerView. So even if the size of the item will change, you still can set this to true.

      – Kimi Chiu
      Jan 2 '17 at 9:38











      12














      The ListView had a similar named function that I think did reflect info about the size of the individual list item heights. The documentation for RecyclerView pretty clearly states it is referring to the size of the RecyclerView itself, not the size of its items.



      From the RecyclerView source comment above the setHasFixedSize() method:



       * RecyclerView can perform several optimizations if it can know in advance that changes in
      * adapter content cannot change the size of the RecyclerView itself.
      * If your use of RecyclerView falls into this category, set this to true.





      share|improve this answer



















      • 13





        But how is RecyclerView's "size" defined? Is it the size visible on screen only, or the full size of the RecyclerView, which equals (sum of item heights + padding + spacing)?

        – Vicky Chijwani
        May 14 '15 at 18:37








      • 1





        Indeed, this needs more info. If you remove items and the recyclerview shrinks, is it considered that is had changed size?

        – Henrique de Sousa
        Jul 3 '15 at 17:53






      • 2





        I would think of it like how a TextView can lay itself out. If you specify wrap_content, then when you set text the TextView can request a layout pass and change the amount of space it occupies on the screen. If you specify match_parent or a fixed dimension, then TextView will not request a layout pass because the size is fixed and the amount of text insde will never change the amount of space occupied. RecyclerView is the same. setHasFixedSize() hints to RV it should never need to request layout passes based on changes to the adapter items.

        – dangVarmit
        Jul 6 '15 at 17:56













      • @dangVarmit nice explanation!

        – howerknea
        Jun 27 '16 at 8:55
















      12














      The ListView had a similar named function that I think did reflect info about the size of the individual list item heights. The documentation for RecyclerView pretty clearly states it is referring to the size of the RecyclerView itself, not the size of its items.



      From the RecyclerView source comment above the setHasFixedSize() method:



       * RecyclerView can perform several optimizations if it can know in advance that changes in
      * adapter content cannot change the size of the RecyclerView itself.
      * If your use of RecyclerView falls into this category, set this to true.





      share|improve this answer



















      • 13





        But how is RecyclerView's "size" defined? Is it the size visible on screen only, or the full size of the RecyclerView, which equals (sum of item heights + padding + spacing)?

        – Vicky Chijwani
        May 14 '15 at 18:37








      • 1





        Indeed, this needs more info. If you remove items and the recyclerview shrinks, is it considered that is had changed size?

        – Henrique de Sousa
        Jul 3 '15 at 17:53






      • 2





        I would think of it like how a TextView can lay itself out. If you specify wrap_content, then when you set text the TextView can request a layout pass and change the amount of space it occupies on the screen. If you specify match_parent or a fixed dimension, then TextView will not request a layout pass because the size is fixed and the amount of text insde will never change the amount of space occupied. RecyclerView is the same. setHasFixedSize() hints to RV it should never need to request layout passes based on changes to the adapter items.

        – dangVarmit
        Jul 6 '15 at 17:56













      • @dangVarmit nice explanation!

        – howerknea
        Jun 27 '16 at 8:55














      12












      12








      12







      The ListView had a similar named function that I think did reflect info about the size of the individual list item heights. The documentation for RecyclerView pretty clearly states it is referring to the size of the RecyclerView itself, not the size of its items.



      From the RecyclerView source comment above the setHasFixedSize() method:



       * RecyclerView can perform several optimizations if it can know in advance that changes in
      * adapter content cannot change the size of the RecyclerView itself.
      * If your use of RecyclerView falls into this category, set this to true.





      share|improve this answer













      The ListView had a similar named function that I think did reflect info about the size of the individual list item heights. The documentation for RecyclerView pretty clearly states it is referring to the size of the RecyclerView itself, not the size of its items.



      From the RecyclerView source comment above the setHasFixedSize() method:



       * RecyclerView can perform several optimizations if it can know in advance that changes in
      * adapter content cannot change the size of the RecyclerView itself.
      * If your use of RecyclerView falls into this category, set this to true.






      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Feb 25 '15 at 1:52









      dangVarmitdangVarmit

      4,51821523




      4,51821523








      • 13





        But how is RecyclerView's "size" defined? Is it the size visible on screen only, or the full size of the RecyclerView, which equals (sum of item heights + padding + spacing)?

        – Vicky Chijwani
        May 14 '15 at 18:37








      • 1





        Indeed, this needs more info. If you remove items and the recyclerview shrinks, is it considered that is had changed size?

        – Henrique de Sousa
        Jul 3 '15 at 17:53






      • 2





        I would think of it like how a TextView can lay itself out. If you specify wrap_content, then when you set text the TextView can request a layout pass and change the amount of space it occupies on the screen. If you specify match_parent or a fixed dimension, then TextView will not request a layout pass because the size is fixed and the amount of text insde will never change the amount of space occupied. RecyclerView is the same. setHasFixedSize() hints to RV it should never need to request layout passes based on changes to the adapter items.

        – dangVarmit
        Jul 6 '15 at 17:56













      • @dangVarmit nice explanation!

        – howerknea
        Jun 27 '16 at 8:55














      • 13





        But how is RecyclerView's "size" defined? Is it the size visible on screen only, or the full size of the RecyclerView, which equals (sum of item heights + padding + spacing)?

        – Vicky Chijwani
        May 14 '15 at 18:37








      • 1





        Indeed, this needs more info. If you remove items and the recyclerview shrinks, is it considered that is had changed size?

        – Henrique de Sousa
        Jul 3 '15 at 17:53






      • 2





        I would think of it like how a TextView can lay itself out. If you specify wrap_content, then when you set text the TextView can request a layout pass and change the amount of space it occupies on the screen. If you specify match_parent or a fixed dimension, then TextView will not request a layout pass because the size is fixed and the amount of text insde will never change the amount of space occupied. RecyclerView is the same. setHasFixedSize() hints to RV it should never need to request layout passes based on changes to the adapter items.

        – dangVarmit
        Jul 6 '15 at 17:56













      • @dangVarmit nice explanation!

        – howerknea
        Jun 27 '16 at 8:55








      13




      13





      But how is RecyclerView's "size" defined? Is it the size visible on screen only, or the full size of the RecyclerView, which equals (sum of item heights + padding + spacing)?

      – Vicky Chijwani
      May 14 '15 at 18:37







      But how is RecyclerView's "size" defined? Is it the size visible on screen only, or the full size of the RecyclerView, which equals (sum of item heights + padding + spacing)?

      – Vicky Chijwani
      May 14 '15 at 18:37






      1




      1





      Indeed, this needs more info. If you remove items and the recyclerview shrinks, is it considered that is had changed size?

      – Henrique de Sousa
      Jul 3 '15 at 17:53





      Indeed, this needs more info. If you remove items and the recyclerview shrinks, is it considered that is had changed size?

      – Henrique de Sousa
      Jul 3 '15 at 17:53




      2




      2





      I would think of it like how a TextView can lay itself out. If you specify wrap_content, then when you set text the TextView can request a layout pass and change the amount of space it occupies on the screen. If you specify match_parent or a fixed dimension, then TextView will not request a layout pass because the size is fixed and the amount of text insde will never change the amount of space occupied. RecyclerView is the same. setHasFixedSize() hints to RV it should never need to request layout passes based on changes to the adapter items.

      – dangVarmit
      Jul 6 '15 at 17:56







      I would think of it like how a TextView can lay itself out. If you specify wrap_content, then when you set text the TextView can request a layout pass and change the amount of space it occupies on the screen. If you specify match_parent or a fixed dimension, then TextView will not request a layout pass because the size is fixed and the amount of text insde will never change the amount of space occupied. RecyclerView is the same. setHasFixedSize() hints to RV it should never need to request layout passes based on changes to the adapter items.

      – dangVarmit
      Jul 6 '15 at 17:56















      @dangVarmit nice explanation!

      – howerknea
      Jun 27 '16 at 8:55





      @dangVarmit nice explanation!

      – howerknea
      Jun 27 '16 at 8:55











      3














      setHasFixedSize(true) means the RecyclerView has children (items) that has fixed width and height. This allows the RecyclerView to optimize better by figuring out the exact height and width of the entire list based on the your adapter.






      share|improve this answer



















      • 4





        That's not what @dangVarmit has suggested.

        – strangetimes
        Jul 19 '16 at 0:14






      • 1





        Misleading, it's actually the Recycler view size, not the size of the content

        – Benoit
        Apr 16 '18 at 14:28
















      3














      setHasFixedSize(true) means the RecyclerView has children (items) that has fixed width and height. This allows the RecyclerView to optimize better by figuring out the exact height and width of the entire list based on the your adapter.






      share|improve this answer



















      • 4





        That's not what @dangVarmit has suggested.

        – strangetimes
        Jul 19 '16 at 0:14






      • 1





        Misleading, it's actually the Recycler view size, not the size of the content

        – Benoit
        Apr 16 '18 at 14:28














      3












      3








      3







      setHasFixedSize(true) means the RecyclerView has children (items) that has fixed width and height. This allows the RecyclerView to optimize better by figuring out the exact height and width of the entire list based on the your adapter.






      share|improve this answer













      setHasFixedSize(true) means the RecyclerView has children (items) that has fixed width and height. This allows the RecyclerView to optimize better by figuring out the exact height and width of the entire list based on the your adapter.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Oct 7 '15 at 22:43









      Calvin ParkCalvin Park

      7131921




      7131921








      • 4





        That's not what @dangVarmit has suggested.

        – strangetimes
        Jul 19 '16 at 0:14






      • 1





        Misleading, it's actually the Recycler view size, not the size of the content

        – Benoit
        Apr 16 '18 at 14:28














      • 4





        That's not what @dangVarmit has suggested.

        – strangetimes
        Jul 19 '16 at 0:14






      • 1





        Misleading, it's actually the Recycler view size, not the size of the content

        – Benoit
        Apr 16 '18 at 14:28








      4




      4





      That's not what @dangVarmit has suggested.

      – strangetimes
      Jul 19 '16 at 0:14





      That's not what @dangVarmit has suggested.

      – strangetimes
      Jul 19 '16 at 0:14




      1




      1





      Misleading, it's actually the Recycler view size, not the size of the content

      – Benoit
      Apr 16 '18 at 14:28





      Misleading, it's actually the Recycler view size, not the size of the content

      – Benoit
      Apr 16 '18 at 14:28











      2














      Wen we set setHasFixedSize(true) on RecyclerView that means recycler's size is fixed and is not affected by the adapter contents. And in this case onLayout is not called on recycler when we update the adaptrer's data (but there is an exception).



      Let's go to the example:



      RecyclerView has a RecyclerViewDataObserver (find default implemntation in this file) with several methods, the main important is:



      void triggerUpdateProcessor() {
      if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) {
      ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable);
      } else {
      mAdapterUpdateDuringMeasure = true;
      requestLayout();
      }
      }


      This method is called if we set setHasFixedSize(true) and update an adapter's data via: notifyItemRangeChanged, notifyItemRangeInserted, notifyItemRangeRemoved or notifyItemRangeMoved. In this case there is no calls to the recycler's onLayout, but there is calls to requestLayout for updating childs.



      But if we set setHasFixedSize(true) and update an adapter's data via notifyItemChanged then there is call to onChange of the recycler's default RecyclerViewDataObserver and no calls to triggerUpdateProcessor. In this case the recycler onLayout is called whenever we set setHasFixedSize true or false.



      // no calls to triggerUpdateProcessor
      @Override
      public void onChanged() {
      assertNotInLayoutOrScroll(null);
      mState.mStructureChanged = true;

      processDataSetCompletelyChanged(true);
      if (!mAdapterHelper.hasPendingUpdates()) {
      requestLayout();
      }
      }

      // calls to triggerUpdateProcessor
      @Override
      public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
      assertNotInLayoutOrScroll(null);
      if (mAdapterHelper.onItemRangeChanged(positionStart, itemCount, payload)) {
      triggerUpdateProcessor();
      }
      }


      How to check by yourself:



      Create custom RecyclerView and override:



      override fun requestLayout() {
      Log.d("CustomRecycler", "requestLayout is called")
      super.requestLayout()
      }

      override fun invalidate() {
      Log.d("CustomRecycler", "invalidate is called")
      super.invalidate()
      }

      override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
      Log.d("CustomRecycler", "onLayout is called")
      super.onLayout(changed, l, t, r, b)
      }


      Set the recycler size to match_parent (in xml). Try to update adapter's data using replaceData and replaceOne with seting setHasFixedSize(true) and then false.



      // onLayout is called every time
      fun replaceAll(data: List<String>) {
      dataSet.clear()
      dataSet.addAll(data)
      this.notifyDataSetChanged()
      }

      // onLayout is called only for setHasFixedSize(false)
      fun replaceOne(data: List<String>) {
      dataSet.removeAt(0)
      dataSet.addAll(0, data[0])
      this.notifyItemChanged(0)
      }


      And check your log.



      My log:



      // for replaceAll
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: onMeasure is called
      D/CustomRecycler: onMeasure is called
      D/CustomRecycler: onLayout
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: onDraw is called

      // for replaceOne
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: onDraw is called
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: onDraw is called


      Summarize:



      If we set setHasFixedSize(true) and update adapter's data with notifying an observer in some other way than calling notifyDataSetChanged, then you have some perfomance, because the is no calls to the recycler onLayout method.






      share|improve this answer


























      • Did you tested with RecyclerView of height using wrap_content or match_parent ?

        – Lubos Mudrak
        Dec 14 '18 at 15:22
















      2














      Wen we set setHasFixedSize(true) on RecyclerView that means recycler's size is fixed and is not affected by the adapter contents. And in this case onLayout is not called on recycler when we update the adaptrer's data (but there is an exception).



      Let's go to the example:



      RecyclerView has a RecyclerViewDataObserver (find default implemntation in this file) with several methods, the main important is:



      void triggerUpdateProcessor() {
      if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) {
      ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable);
      } else {
      mAdapterUpdateDuringMeasure = true;
      requestLayout();
      }
      }


      This method is called if we set setHasFixedSize(true) and update an adapter's data via: notifyItemRangeChanged, notifyItemRangeInserted, notifyItemRangeRemoved or notifyItemRangeMoved. In this case there is no calls to the recycler's onLayout, but there is calls to requestLayout for updating childs.



      But if we set setHasFixedSize(true) and update an adapter's data via notifyItemChanged then there is call to onChange of the recycler's default RecyclerViewDataObserver and no calls to triggerUpdateProcessor. In this case the recycler onLayout is called whenever we set setHasFixedSize true or false.



      // no calls to triggerUpdateProcessor
      @Override
      public void onChanged() {
      assertNotInLayoutOrScroll(null);
      mState.mStructureChanged = true;

      processDataSetCompletelyChanged(true);
      if (!mAdapterHelper.hasPendingUpdates()) {
      requestLayout();
      }
      }

      // calls to triggerUpdateProcessor
      @Override
      public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
      assertNotInLayoutOrScroll(null);
      if (mAdapterHelper.onItemRangeChanged(positionStart, itemCount, payload)) {
      triggerUpdateProcessor();
      }
      }


      How to check by yourself:



      Create custom RecyclerView and override:



      override fun requestLayout() {
      Log.d("CustomRecycler", "requestLayout is called")
      super.requestLayout()
      }

      override fun invalidate() {
      Log.d("CustomRecycler", "invalidate is called")
      super.invalidate()
      }

      override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
      Log.d("CustomRecycler", "onLayout is called")
      super.onLayout(changed, l, t, r, b)
      }


      Set the recycler size to match_parent (in xml). Try to update adapter's data using replaceData and replaceOne with seting setHasFixedSize(true) and then false.



      // onLayout is called every time
      fun replaceAll(data: List<String>) {
      dataSet.clear()
      dataSet.addAll(data)
      this.notifyDataSetChanged()
      }

      // onLayout is called only for setHasFixedSize(false)
      fun replaceOne(data: List<String>) {
      dataSet.removeAt(0)
      dataSet.addAll(0, data[0])
      this.notifyItemChanged(0)
      }


      And check your log.



      My log:



      // for replaceAll
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: onMeasure is called
      D/CustomRecycler: onMeasure is called
      D/CustomRecycler: onLayout
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: onDraw is called

      // for replaceOne
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: onDraw is called
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: onDraw is called


      Summarize:



      If we set setHasFixedSize(true) and update adapter's data with notifying an observer in some other way than calling notifyDataSetChanged, then you have some perfomance, because the is no calls to the recycler onLayout method.






      share|improve this answer


























      • Did you tested with RecyclerView of height using wrap_content or match_parent ?

        – Lubos Mudrak
        Dec 14 '18 at 15:22














      2












      2








      2







      Wen we set setHasFixedSize(true) on RecyclerView that means recycler's size is fixed and is not affected by the adapter contents. And in this case onLayout is not called on recycler when we update the adaptrer's data (but there is an exception).



      Let's go to the example:



      RecyclerView has a RecyclerViewDataObserver (find default implemntation in this file) with several methods, the main important is:



      void triggerUpdateProcessor() {
      if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) {
      ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable);
      } else {
      mAdapterUpdateDuringMeasure = true;
      requestLayout();
      }
      }


      This method is called if we set setHasFixedSize(true) and update an adapter's data via: notifyItemRangeChanged, notifyItemRangeInserted, notifyItemRangeRemoved or notifyItemRangeMoved. In this case there is no calls to the recycler's onLayout, but there is calls to requestLayout for updating childs.



      But if we set setHasFixedSize(true) and update an adapter's data via notifyItemChanged then there is call to onChange of the recycler's default RecyclerViewDataObserver and no calls to triggerUpdateProcessor. In this case the recycler onLayout is called whenever we set setHasFixedSize true or false.



      // no calls to triggerUpdateProcessor
      @Override
      public void onChanged() {
      assertNotInLayoutOrScroll(null);
      mState.mStructureChanged = true;

      processDataSetCompletelyChanged(true);
      if (!mAdapterHelper.hasPendingUpdates()) {
      requestLayout();
      }
      }

      // calls to triggerUpdateProcessor
      @Override
      public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
      assertNotInLayoutOrScroll(null);
      if (mAdapterHelper.onItemRangeChanged(positionStart, itemCount, payload)) {
      triggerUpdateProcessor();
      }
      }


      How to check by yourself:



      Create custom RecyclerView and override:



      override fun requestLayout() {
      Log.d("CustomRecycler", "requestLayout is called")
      super.requestLayout()
      }

      override fun invalidate() {
      Log.d("CustomRecycler", "invalidate is called")
      super.invalidate()
      }

      override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
      Log.d("CustomRecycler", "onLayout is called")
      super.onLayout(changed, l, t, r, b)
      }


      Set the recycler size to match_parent (in xml). Try to update adapter's data using replaceData and replaceOne with seting setHasFixedSize(true) and then false.



      // onLayout is called every time
      fun replaceAll(data: List<String>) {
      dataSet.clear()
      dataSet.addAll(data)
      this.notifyDataSetChanged()
      }

      // onLayout is called only for setHasFixedSize(false)
      fun replaceOne(data: List<String>) {
      dataSet.removeAt(0)
      dataSet.addAll(0, data[0])
      this.notifyItemChanged(0)
      }


      And check your log.



      My log:



      // for replaceAll
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: onMeasure is called
      D/CustomRecycler: onMeasure is called
      D/CustomRecycler: onLayout
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: onDraw is called

      // for replaceOne
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: onDraw is called
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: onDraw is called


      Summarize:



      If we set setHasFixedSize(true) and update adapter's data with notifying an observer in some other way than calling notifyDataSetChanged, then you have some perfomance, because the is no calls to the recycler onLayout method.






      share|improve this answer















      Wen we set setHasFixedSize(true) on RecyclerView that means recycler's size is fixed and is not affected by the adapter contents. And in this case onLayout is not called on recycler when we update the adaptrer's data (but there is an exception).



      Let's go to the example:



      RecyclerView has a RecyclerViewDataObserver (find default implemntation in this file) with several methods, the main important is:



      void triggerUpdateProcessor() {
      if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) {
      ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable);
      } else {
      mAdapterUpdateDuringMeasure = true;
      requestLayout();
      }
      }


      This method is called if we set setHasFixedSize(true) and update an adapter's data via: notifyItemRangeChanged, notifyItemRangeInserted, notifyItemRangeRemoved or notifyItemRangeMoved. In this case there is no calls to the recycler's onLayout, but there is calls to requestLayout for updating childs.



      But if we set setHasFixedSize(true) and update an adapter's data via notifyItemChanged then there is call to onChange of the recycler's default RecyclerViewDataObserver and no calls to triggerUpdateProcessor. In this case the recycler onLayout is called whenever we set setHasFixedSize true or false.



      // no calls to triggerUpdateProcessor
      @Override
      public void onChanged() {
      assertNotInLayoutOrScroll(null);
      mState.mStructureChanged = true;

      processDataSetCompletelyChanged(true);
      if (!mAdapterHelper.hasPendingUpdates()) {
      requestLayout();
      }
      }

      // calls to triggerUpdateProcessor
      @Override
      public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
      assertNotInLayoutOrScroll(null);
      if (mAdapterHelper.onItemRangeChanged(positionStart, itemCount, payload)) {
      triggerUpdateProcessor();
      }
      }


      How to check by yourself:



      Create custom RecyclerView and override:



      override fun requestLayout() {
      Log.d("CustomRecycler", "requestLayout is called")
      super.requestLayout()
      }

      override fun invalidate() {
      Log.d("CustomRecycler", "invalidate is called")
      super.invalidate()
      }

      override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
      Log.d("CustomRecycler", "onLayout is called")
      super.onLayout(changed, l, t, r, b)
      }


      Set the recycler size to match_parent (in xml). Try to update adapter's data using replaceData and replaceOne with seting setHasFixedSize(true) and then false.



      // onLayout is called every time
      fun replaceAll(data: List<String>) {
      dataSet.clear()
      dataSet.addAll(data)
      this.notifyDataSetChanged()
      }

      // onLayout is called only for setHasFixedSize(false)
      fun replaceOne(data: List<String>) {
      dataSet.removeAt(0)
      dataSet.addAll(0, data[0])
      this.notifyItemChanged(0)
      }


      And check your log.



      My log:



      // for replaceAll
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: onMeasure is called
      D/CustomRecycler: onMeasure is called
      D/CustomRecycler: onLayout
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: onDraw is called

      // for replaceOne
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: onDraw is called
      D/CustomRecycler: requestLayout is called
      D/CustomRecycler: onDraw is called


      Summarize:



      If we set setHasFixedSize(true) and update adapter's data with notifying an observer in some other way than calling notifyDataSetChanged, then you have some perfomance, because the is no calls to the recycler onLayout method.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Nov 14 '18 at 6:38

























      answered Nov 12 '18 at 12:10









      bitvalebitvale

      499514




      499514













      • Did you tested with RecyclerView of height using wrap_content or match_parent ?

        – Lubos Mudrak
        Dec 14 '18 at 15:22



















      • Did you tested with RecyclerView of height using wrap_content or match_parent ?

        – Lubos Mudrak
        Dec 14 '18 at 15:22

















      Did you tested with RecyclerView of height using wrap_content or match_parent ?

      – Lubos Mudrak
      Dec 14 '18 at 15:22





      Did you tested with RecyclerView of height using wrap_content or match_parent ?

      – Lubos Mudrak
      Dec 14 '18 at 15:22











      0














      It affects the animations of the recyclerview, if it's false.. the insert and remove animations won't show. so make sure it's true in case you added animation for the recyclerview.






      share|improve this answer




























        0














        It affects the animations of the recyclerview, if it's false.. the insert and remove animations won't show. so make sure it's true in case you added animation for the recyclerview.






        share|improve this answer


























          0












          0








          0







          It affects the animations of the recyclerview, if it's false.. the insert and remove animations won't show. so make sure it's true in case you added animation for the recyclerview.






          share|improve this answer













          It affects the animations of the recyclerview, if it's false.. the insert and remove animations won't show. so make sure it's true in case you added animation for the recyclerview.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Dec 23 '17 at 8:36









          Alaa AbuZarifaAlaa AbuZarifa

          328316




          328316























              0














              If the size of the RecyclerView (the RecyclerView itself)



              ... does not depend on the adapter content:



              mRecyclerView.setHasFixedSize(true);


              ...depends on the adapter content:



              mRecyclerView.setHasFixedSize(false);





              share|improve this answer






























                0














                If the size of the RecyclerView (the RecyclerView itself)



                ... does not depend on the adapter content:



                mRecyclerView.setHasFixedSize(true);


                ...depends on the adapter content:



                mRecyclerView.setHasFixedSize(false);





                share|improve this answer




























                  0












                  0








                  0







                  If the size of the RecyclerView (the RecyclerView itself)



                  ... does not depend on the adapter content:



                  mRecyclerView.setHasFixedSize(true);


                  ...depends on the adapter content:



                  mRecyclerView.setHasFixedSize(false);





                  share|improve this answer















                  If the size of the RecyclerView (the RecyclerView itself)



                  ... does not depend on the adapter content:



                  mRecyclerView.setHasFixedSize(true);


                  ...depends on the adapter content:



                  mRecyclerView.setHasFixedSize(false);






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Aug 6 '18 at 10:24









                  Nic3500

                  3,33281829




                  3,33281829










                  answered Aug 6 '18 at 7:55









                  Alok SinghAlok Singh

                  1099




                  1099






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f28709220%2funderstanding-recyclerview-sethasfixedsize%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Florida Star v. B. J. F.

                      Danny Elfman

                      Lugert, Oklahoma