diff options
author | Sara Seppola <sara@vaadin.com> | 2014-11-04 11:44:45 +0200 |
---|---|---|
committer | Sauli Tähkäpää <sauli@vaadin.com> | 2014-11-25 14:42:44 +0200 |
commit | 0507127d674d67052ff2e2d9f139e3a69d871169 (patch) | |
tree | 05be65646882d885a2861eaee4210d1e56cd7928 | |
parent | 53c1e10c0a76f26bdd055916e794621264001f52 (diff) | |
download | vaadin-framework-0507127d674d67052ff2e2d9f139e3a69d871169.tar.gz vaadin-framework-0507127d674d67052ff2e2d9f139e3a69d871169.zip |
Table is not caching thousands of rows in vain (#13576)
Change-Id: I6f6382dd3468db40c36e507b94f84ab1191e100f
3 files changed, 167 insertions, 10 deletions
diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java index 961e32b290..6c241f1033 100644 --- a/client/src/com/vaadin/client/ui/VScrollTable.java +++ b/client/src/com/vaadin/client/ui/VScrollTable.java @@ -2600,11 +2600,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets, @Override public void run() { + if (client.hasActiveRequest() || navKeyDown) { // if client connection is busy, don't bother loading it more VConsole.log("Postponed rowfetch"); schedule(250); - } else if (!updatedReqRows && allRenderedRowsAreNew()) { + } else if (allRenderedRowsAreNew() && !updatedReqRows) { /* * If all rows are new, there might have been a server-side call @@ -2625,6 +2626,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, setReqRows(last - getReqFirstRow() + 1); updatedReqRows = true; schedule(250); + } else { int firstRendered = scrollBody.getFirstRendered(); @@ -2712,6 +2714,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, client.updateVariable(paintableId, "firstvisible", firstRowInViewPort, false); } + client.updateVariable(paintableId, "reqfirstrow", reqFirstRow, false); client.updateVariable(paintableId, "reqrows", reqRows, true); @@ -4208,7 +4211,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } /** - * Returns the expand ration of the cell + * Returns the expand ratio of the cell * * @return The expand ratio */ @@ -4696,10 +4699,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } public int getLastRendered() { + return lastRendered; } public int getFirstRendered() { + return firstRendered; } @@ -4783,10 +4788,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } else if (firstIndex + rows == firstRendered) { final VScrollTableRow[] rowArray = new VScrollTableRow[rows]; int i = rows; + while (it.hasNext()) { i--; rowArray[i] = prepareRow((UIDL) it.next()); } + for (i = 0; i < rows; i++) { addRowBeforeFirstRendered(rowArray[i]); firstRendered--; @@ -4811,10 +4818,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets, setLastRendered(lastRendered + 1); setContainerHeight(); fixSpacers(); + while (it.hasNext()) { addRow(prepareRow((UIDL) it.next())); setLastRendered(lastRendered + 1); } + fixSpacers(); } @@ -4829,6 +4838,14 @@ public class VScrollTable extends FlowPanel implements HasWidgets, * has changed since the last request. */ protected void ensureCacheFilled() { + + /** + * Fixes cache issue #13576 where unnecessary rows are fetched + */ + if (isLazyScrollerActive()) { + return; + } + int reactFirstRow = (int) (firstRowInViewPort - pageLength * cache_react_rate); int reactLastRow = (int) (firstRowInViewPort + pageLength + pageLength @@ -6136,7 +6153,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, touchStart = event; Touch touch = event.getChangedTouches().get(0); // save position to fields, touches in events are same - // isntance during the operation. + // instance during the operation. touchStartX = touch.getClientX(); touchStartY = touch.getClientY(); /* @@ -6444,8 +6461,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, startRow = focusedRow; selectionRangeStart = focusedRow; // If start row is null then we have a multipage selection - // from - // above + // from above if (startRow == null) { startRow = (VScrollTableRow) scrollBody.iterator() .next(); @@ -7280,6 +7296,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, } if (preLimit < firstRendered) { // need some rows to the beginning of the rendered area + rowRequestHandler .setReqFirstRow((int) (firstRowInViewPort - pageLength * cache_rate)); @@ -7665,13 +7682,13 @@ public class VScrollTable extends FlowPanel implements HasWidgets, // viewport selectLastItemInNextRender = true; multiselectPending = shift; - scrollByPagelenght(1); + scrollByPagelength(1); } } } } else { /* No selections, go page down by scrolling */ - scrollByPagelenght(1); + scrollByPagelength(1); } return true; } @@ -7717,13 +7734,13 @@ public class VScrollTable extends FlowPanel implements HasWidgets, // viewport selectFirstItemInNextRender = true; multiselectPending = shift; - scrollByPagelenght(-1); + scrollByPagelength(-1); } } } } else { /* No selections, go page up by scrolling */ - scrollByPagelenght(-1); + scrollByPagelength(-1); } return true; @@ -7797,7 +7814,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, .getRowHeight()); } - private void scrollByPagelenght(int i) { + private void scrollByPagelength(int i) { int pixels = i * scrollBodyPanel.getOffsetHeight(); int newPixels = scrollBodyPanel.getScrollPosition() + pixels; if (newPixels < 0) { diff --git a/uitest/src/com/vaadin/tests/components/table/TableCacheMinimizingOnFetchRows.java b/uitest/src/com/vaadin/tests/components/table/TableCacheMinimizingOnFetchRows.java new file mode 100644 index 0000000000..745f2344a3 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableCacheMinimizingOnFetchRows.java @@ -0,0 +1,92 @@ +package com.vaadin.tests.components.table; + +import java.io.Serializable; +import java.util.List; + +import com.vaadin.data.util.BeanContainer; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Table; + +@SuppressWarnings("serial") +public class TableCacheMinimizingOnFetchRows extends AbstractTestUIWithLog { + + @Override + protected void setup(VaadinRequest request) { + getLayout().setMargin(true); + + final Table table = new Table("Beans of All Sorts"); + + BeanContainer<String, Bean> beans = new BeanContainer<String, Bean>( + Bean.class) { + @Override + public List<String> getItemIds(int startIndex, int numberOfIds) { + + // numberOfIds should be about 60 after scrolling down the table + log.log("requested " + numberOfIds + " rows"); + + return super.getItemIds(startIndex, numberOfIds); + } + }; + beans.setBeanIdProperty("name"); + + for (int i = 0; i < 10000; i++) { + beans.addBean(new Bean("Common bean" + i, i)); + } + + table.setContainerDataSource(beans); + table.setPageLength(20); + table.setVisibleColumns(new Object[] { "name", "value" }); + table.setWidth("800px"); + + Button button = new Button("scroll down"); + button.addClickListener(new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + table.setCurrentPageFirstItemIndex(table.size()); + } + }); + + addComponent(table); + addComponent(button); + } + + public class Bean implements Serializable { + + String name; + int value; + + public Bean(String name, int value) { + this.name = name; + this.value = value; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + } + + @Override + protected String getTestDescription() { + return "Ensure that when scrolling from top to bottom in a big table with 10000 items, not all rows in the range are cached"; + } + + @Override + protected Integer getTicketNumber() { + return 13576; + } +}
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/components/table/TableCacheMinimizingOnFetchRowsTest.java b/uitest/src/com/vaadin/tests/components/table/TableCacheMinimizingOnFetchRowsTest.java new file mode 100644 index 0000000000..edb0f3851a --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableCacheMinimizingOnFetchRowsTest.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.table; + +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.Test; +import org.openqa.selenium.By; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class TableCacheMinimizingOnFetchRowsTest extends MultiBrowserTest { + + @Test + public void testCacheSize() throws InterruptedException { + + openTestURL(); + + scrollToBottomOfTable(); + + // the row request might vary slightly with different browsers + String logtext1 = "requested 60 rows"; + String logtext2 = "requested 61 rows"; + + assertThat("Requested cached rows did not match expected", + logContainsText(logtext1) || logContainsText(logtext2)); + + } + + private void scrollToBottomOfTable() { + waitForElementPresent(By.className("v-button")); + $(ButtonElement.class).first().click(); + } +} |