Implement ListModel and TreeModel"

From Documentation
m
Line 26: Line 26:
 
     }
 
     }
 
     public void sort(Comparator cmpr, boolean ascending) {
 
     public void sort(Comparator cmpr, boolean ascending) {
 +
        _cache = null; //purge cache
 
         _descending = !(_ascending = ascending);
 
         _descending = !(_ascending = ascending);
 
         _orderBy = ((FieldComparator)cmpr).getRawOrderBy();
 
         _orderBy = ((FieldComparator)cmpr).getRawOrderBy();
Line 31: Line 32:
 
             //On other hand, if you specifies your own comparator, such as sortAscending="${mycmpr}",
 
             //On other hand, if you specifies your own comparator, such as sortAscending="${mycmpr}",
 
             //then, cmpr will be the comparator you assigned
 
             //then, cmpr will be the comparator you assigned
 +
        fireEvent(ListDataEvent.CONTENTS_CHANGED, -1, -1);
 
     }
 
     }
 
}
 
}
 
</source>
 
</source>
 +
 +
The implementation of <javadoc type="interface" method="sort(java.util.Comparator, boolean)">org.zkoss.zul.ListModelExt</javadoc> generally has to purge the cache, store the sorting direction and field, and then fire <javadoc method="CONTENTS_CHANGED">org.zkoss.zul.event.ListDataEvent</javadoc> to reload the content.
 +
 +
The field to sort against has to be retrieved from the given comparator. If you specify <code>"auto(fieldName)"</code> to <javadoc method="setSort(java.lang.String)">org.zkoss.zul.Listheader</javadoc>, then the comparator is an instance of <javadoc>org.zkoss.zul.FieldComparator</javadoc>, and you could retrieve the field's name from <javadoc method="getRawOrderBy()">org.zkoss.zul.FieldComparator</javadoc>.
 +
 +
If you'd like to use your own comparator, you have to carry the information in it and then retrieve it back when <javadoc type="interface" method="sort(java.util.Comparator, boolean)">org.zkoss.zul.ListModelExt</javadoc> is called.
 +
 
For a real example, please refer to [[Small Talks/2009/July/Handling huge data using ZK|Small Talk: Handling huge data using ZK]].
 
For a real example, please refer to [[Small Talks/2009/July/Handling huge data using ZK|Small Talk: Handling huge data using ZK]].
  

Revision as of 01:57, 10 March 2011


Implement ListModel and TreeModel


The default implementation of models, such as ListModelList and DefaultTreeModel assumes all data are available in the memory. It is not practical if a model has a lot of data. For huge data, it is suggested to implement your own model by loading and caching only a portion of data at a time.

To implement your own model, you could extend from AbstractListModel, AbstractGroupsModel and DefaultTreeModel as described in the Model section. To implement a model that supports sorting, you have to implement ListModelExt too. Each time an user requires sorting, ListModelExt.sort(Comparator, boolean) will be called and the implementation usually clears the cache and re-generate the SQL statement accordingly.

Here is some pseudo code:

public class FooListModel extends AbstractListModel implements ListModelExt {
    private Object[] _cache;
    private int _beginOffset;
    private String _orderBy;
    private boolean _ascending, _descending;

    public int getSize() {
        return /*SELECT COUNT(*) FROM ..
    }
    public Object getElementAt(int index) {
        if (_cache == null || index < _beginOffset || index >= _beginOffset + _cache.length) {
            loadToCache(index, 100); //SELECT ... FROM .... OFFSET index LIMIT 100
                //if _ascending, ORDER BY _orderBy ASC
                //if _descending, ORDER BY _orderBy DSC
        }
        return _cache[index - _beginOffset];
    }
    public void sort(Comparator cmpr, boolean ascending) {
        _cache = null; //purge cache
        _descending = !(_ascending = ascending);
        _orderBy = ((FieldComparator)cmpr).getRawOrderBy();
             //Here we assume sort="auto(fieldName)" is specified in ZUML, so cmpr is FieldComparator
             //On other hand, if you specifies your own comparator, such as sortAscending="${mycmpr}",
             //then, cmpr will be the comparator you assigned
        fireEvent(ListDataEvent.CONTENTS_CHANGED, -1, -1);
    }
}

The implementation of ListModelExt.sort(Comparator, boolean) generally has to purge the cache, store the sorting direction and field, and then fire ListDataEvent.CONTENTS_CHANGED to reload the content.

The field to sort against has to be retrieved from the given comparator. If you specify "auto(fieldName)" to Listheader.setSort(String), then the comparator is an instance of FieldComparator, and you could retrieve the field's name from FieldComparator.getRawOrderBy().

If you'd like to use your own comparator, you have to carry the information in it and then retrieve it back when ListModelExt.sort(Comparator, boolean) is called.

For a real example, please refer to Small Talk: Handling huge data using ZK.

Version History

Last Update : 2011/03/10


Version Date Content
     


Last Update : 2011/03/10


Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.