TechHui

Hawaiʻi's Technology Community

In a real world project I have worked with, I had a serious performance problem with GWT table.
Basically we need to handle tables with hundreds columns, and performance issue of GWT table make the page unusable.

Sure, at the first place, we should not show that big table even for the sake of XUI :). Anyway.. Live Grid of Smart GWT solves this issue by dynamically creating a small table. but we can not use Smart GWT for some reasons..


I had explored several approaches in my spare time.. and try to get some feedbacks from here..

The approach i used here is to introducing horizential paging concept for columns, and hide columns not in the current view. The solution is not perfect.. but at least bring the frozen pages back to life :)

1. Create a wrapper for PagingScrollTable

import java.util.List;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.gen2.table.client.ColumnDefinition;
import com.google.gwt.gen2.table.client.DefaultTableDefinition;
import com.google.gwt.gen2.table.client.PagingScrollTable;
import com.google.gwt.gen2.table.client.TableModel;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.SimplePanel;

public class ColumnPageableTable extends SimplePanel{
private TableModel tableModel;
private DefaultTableDefinition tableDefinition;
private List> visibleColumns;

private int numColumnInOnePage;
private PagingScrollTable curTableInView;
private DockPanel contentPanel = new DockPanel();
private Label next = new Label("next>>");
private Label previous = new Label("previous");
private int curColumnPage = 0 ;

public ColumnPageableTable(TableModel tableModel,
DefaultTableDefinition tableDefinition,
int numColumnInOnePage
) {
this.tableDefinition = tableDefinition;
this.tableModel = tableModel;
this.numColumnInOnePage = numColumnInOnePage;
visibleColumns = tableDefinition.getVisibleColumnDefinitions();
HorizontalPanel navigationPanel = new HorizontalPanel();
navigationPanel.add( previous );
navigationPanel.add( next );
contentPanel.setSize("100%", "100%");
contentPanel.add( navigationPanel, DockPanel.NORTH);
setWidget(contentPanel);
next.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
nextPageColumn();
}
});
previous.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
previousPageColumn();
}
});
gotoPageOfColumn(curColumnPage);
}

public void nextPageColumn(){
if( curColumnPage < getNumOfPagesForColumn() ){
curColumnPage++;
gotoPageOfColumn(curColumnPage);
}
}
public void previousPageColumn(){
if( curColumnPage >= 0 ){
curColumnPage -- ;
gotoPageOfColumn(curColumnPage);
}
}
private int getNumOfPagesForColumn(){
return visibleColumns.size() / numColumnInOnePage +
(visibleColumns.size() % numColumnInOnePage == 0 ? 0 : 1 );
}

public void gotoPageOfColumn( int page ){
int start = page * numColumnInOnePage;
int end = start + numColumnInOnePage -1;
for(int i = 0; i < visibleColumns.size(); i++){
ColumnDefinition colDef = visibleColumns.get(i);
if( i >= start && i <= end ){
tableDefinition.setColumnVisible(colDef, true);
}
else {
tableDefinition.setColumnVisible(colDef, false);
}
}
if( curTableInView == null ){
curTableInView = new PagingScrollTable(tableModel,
tableDefinition);
curTableInView.setSize("100%", "100%");
curTableInView.setPageSize(50);
curTableInView.setCellPadding(3);
curTableInView.setCellSpacing(0);
curTableInView.gotoPage(0, true);
contentPanel.add(curTableInView, DockPanel.CENTER);
contentPanel.setCellHeight(curTableInView, "100%");
contentPanel.setCellWidth(curTableInView, "100%");
}
else {
//TODO:: should not reload from server
curTableInView.reloadPage();
}
}
}

2. Add a test driver
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.gen2.table.client.DefaultTableDefinition;
import com.google.gwt.gen2.table.client.ListColumnDefinition;
import com.google.gwt.gen2.table.client.MutableTableModel;
import com.google.gwt.gen2.table.client.TableModel;
import com.google.gwt.gen2.table.client.TableModelHelper.Request;
import com.google.gwt.gen2.table.client.TableModelHelper.Response;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;
import com.watch.sound.gwt.bigtable.client.table.ColumnPageableTable;

/**
* Entry point classes define onModuleLoad().
*/
public class BigTable implements EntryPoint {

/**
* This is the entry point method.
*/
public void onModuleLoad() {
final int numColumn = 20;
TableModel tm = new MutableTableModel() {
@Override
protected boolean onRowInserted(int beforeRow) {
return false;
}
@Override
protected boolean onRowRemoved(int row) {
return false;
}
@Override
protected boolean onSetRowValue(int row, List rowValue) {
return false;
}
@Override
public void requestRows(
Request request,
com.google.gwt.gen2.table.client.TableModel.Callback callback) {
callback.onRowsReady(request, new Response (){
@Override
public Iterator getRowValues() {
List result = new ArrayList();
for( int i = 0 ; i < 100 ; i++ ){
List row = new ArrayList();
for ( int j = 0; j < numColumn ; j++ ){
row.add( "value" + j );
}
result.add(row);
}
return result.iterator();
}});
}
};
DefaultTableDefinition tableDefinition = new DefaultTableDefinition ();
for( int i = 0; i < numColumn ; i++ ){
ListColumnDefinition colDef = new ListColumnDefinition(i);
colDef.setHeader(0, new HTML("id"+ i));
tableDefinition.addColumnDefinition(colDef);
}
ColumnPageableTable table = new ColumnPageableTable(tm, tableDefinition, 3);
table.setSize("300px","300px");
RootPanel.get().add( table );
}
}

That's it.

-watchsound

Views: 507

Reply to This

Sponsors

web design, web development, localization

© 2018   Created by Daniel Leuck.   Powered by

Badges  |  Report an Issue  |  Terms of Service