Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    ListGrid.refreshRow vs ListGrid.redraw()

    Hi, can you please give me some guidance on when it is better to call refreshRow vs redraw on the entire grid. For example, if we have a grid that is showing 300 records with 15 columns exposed and we need to refresh 100 of those rows with new data, is it better to call ListGrid.redraw or call refreshRow 100 times? My testing suggests that ListGrid.redraw is the better choice by a long shot. What if we only had to update 20 rows out of 300?

    #2
    In general this is very browser dependent, but in the slowest browsers, redraw() begins to be faster than refreshRow() when there are just 2-3 rows to refresh.

    Comment


      #3
      Thanks, so how does this typically work in Chrome which is generally the fastest browser and the one we encourage our users to utilize?

      Comment


        #4
        In general, each refreshRow() call is going to trigger the browser to do a native reflow and repaint of the grid HTML - sometimes multiple times. Redraw() has the JavaScript code do more work but the browser only repaints once.

        We would not recommend trying to tune this on a per-browser basis. You could wake up tomorrow to a new version of Chrome where your strategy is slightly slower. Just use the 2-3 rows means redraw as a rule of thumb.

        Comment


          #5
          Sounds good, I was going up to 100 row refreshes before switching to redraw so I clearly had this wrong. I'll drastically lower that number as you suggest.

          Comment


            #6
            Also, in case you haven't considered it, do bear in mind the difference between 'markForRedraw()' and 'redraw()'.

            markForRedraw() sets up a delayed event to call redraw(), and handles being called repeatedly in an intelligent manner.

            Each time redraw() is called, the grid HTML will be recreated and written back into the DOM (synchronously).
            markForRedraw() on the other hand can be called multiple times within a thread, and will only result in a single actual redraw after the thread of execution completes.

            Comment


              #7
              Thanks for mentioning this. I spent a great deal of time a few years ago testing and debugging when to use redraw vs markForRedraw.

              Because we have so many real-time updates happening in our app, there was often a combination of grid.refreshRow and grid.markForRedraw getting called at the same time. What I observed is that a call to refreshRow would still execute even if markForRedraw had been called right before or afterwards.

              Ideally, there would be some way to call grid.markRowForRefresh and markRowForRefresh would look to see if there was already a call to markForRedraw on the parent grid and thus the call to refresh the row could be ignored.

              Basically, it seems like there is no way to intelligently discard refreshRow or refreshCell calls like you can with grid.markForRedraw. And, as a result, we had to use grid.redraw to prevent lots of slow script errors.

              Admittedly, I need to revisit our code and see if things are behaving differently now. But, can you comment on whether there is any ability to intelligently discard calls to refreshCell or refreshRow if there is a pending redraw of the parent grid?

              Comment


                #8
                You can use the "isDirty()" method to determine if there's a pending redraw on some component. It'd be trivial to add a helper to your app like "refreshCellIfNotDirty"

                Also a side note that you might find yourself calling markForRedraw() / isDirty() on the ListGrid *body* rather than the ListGrid as a whole if you're only refreshing cells within the body HTML and have no need to redraw the rest of the grid (Header, summary row, etc).

                Regards
                Isomorphic Software

                Comment


                  #9
                  Hi, I'm not sure I follow your side note. Are you saying that calling markForRedraw() will sometimes only refresh the body and not refresh headers or summary rows? Or, are you suggesting there is a way to call markForRedraw on the body only ?

                  Further, I have a few more questions on this general topic.

                  1. Can you clarify if I have to call recalculateSummaries after calling redraw or markForRedraw? Or, does recalculateSummaries fire automatically? If I call markForRedraw and then recalculateSummaries, would it be possible that recalculateSummaries would fire first before the grid redraw in response to markForRedraw and it would recalculate summaries with stale data?

                  2. Same questions as above but as they pertain to grid.setHiliteState(). Does it fire automatically or do we have to call it ourselves? Because our app processes real-time stock price updates, we have to evaluate the hilite rules in real-time to see if a new streaming update to our app (ie. new stock price) has triggered updated grid styling because of a hilite rule. To achieve this, we are always calling setHiliteState after calling markForRedraw or redraw. And, this seems to take care of refreshing the grid hilites. But, it feels a little inefficient. If there is a better API to achieve this that I'm missing or a more intelligent way to refresh highlights in response to real-time updates, please let us know.

                  Thanks for all the information on this topic. It has been very helpful eliminating some refresh slowness we've seen lately.

                  Comment


                    #10
                    The side note was pointing out that you can either do "listGrid.markForRedraw()" (marks the entire grid for redraw) or "listGrid.body.markForRedraw()" (only marks the body for redraw).
                    If, within your code, you're actually wanting to call "refreshRow()" but only if the grid isn't dirty, you actually want to avoid the refresh if either the body or the grid as a whole is dirty. Therefore your conditional might be something like
                    Code:
                    if (!myGrid.isDirty() && !myGrid.body.isDirty()) myGrid.refreshRow(...);
                    On your clarifications:
                    1) recalculateSummaries should automatically be called, internally, in response to data change, meaning you don't have to call it explicitly.
                    If you actually have a case where you know the summaries need to be refreshed but it isn't happening automatically, you can call recalculateSummaries yourself to force that refresh. When you do this, this will both recalculate the summary values and refresh to display the new values.
                    Note that simply calling "redraw()" [or "refreshRow()", etc] will not recalculate the summaries.

                    2) setHiliteState() should automatically refresh to display the new hilites - you shouldn't need to explicitly refresh / redraw separately from this API [unless you're refreshing to display some other change].

                    Hopefully that clears things up. If these descriptions don't match what you're observing, or you still have questions, let us know.

                    Thanks
                    Isomorphic Software

                    Comment


                      #11
                      Hi, thanks again. Regarding setHiliteState(), are you suggesting that we shouldn't have to make an explicit call to setHiliteState() if the underlying data changes? Because my experience with 8.2 is that we had to add explicit calls to setHiliteState() in response to any streaming price updates that were received by our application in order for hilites to update in real-time. I'm happy to test again with 8.3 as we migrate if you believe it should happen automatically.

                      Comment


                        #12
                        If the hilite-state, that is, the definitions of the hilites themselves, have changed, then you might need to call setHiliteState() - otherwise, you should be seeing applyHilites() being called automatically on dataChanged(), at least in 8.3p onwards.
                        Last edited by Isomorphic; 8 Mar 2013, 00:17.

                        Comment

                        Working...
                        X