-
FEATURED COMPONENTS
First time here? Check out the FAQ!
Hi forum!!
I have been some years working with ZK software, and I try to document this problem searching an answer, but it was unsuccessful.
The main problem is the memory usage when I’m working with the application with a listbox (huge). I have a lot of records to draw into listbox, but always that I do some action in my application the memory usage increases (paging, open in windows and then closing them, etc).
I have tried different options to configure the listbox, even create my own paging to control how many rows are created, but there aren’t any way to solve it, all is useless.
I have used the MAT to try look the problem, and I could see that the problem is the created objects (listcells, listitems, etc). Is that true? After read a lot of it in this forum I note that this is a usual problem into the ZK community and will be good to solve it as soon as possible. Its possible that I’m doing some wrong, then I put a example to see it.
ZK version: 6.0
Tomcat: v.7
This is my listbox (Javaclass):
public class ListBoxMemory extends SelectorComposer<Component> { private static final long serialVersionUID = 1L; @Init public void init(@ContextParam(ContextType.VIEW) Component view){ Selectors.wireComponents(view, this, false); Selectors.wireEventListeners(view, this); Selectors.wireVariables(view, this, null); } //The binding list private List<MemoryBean> BeanList = new ArrayList<MemoryBean>(); private MemoryBean bean; @Command @NotifyChange("*") public void Start(){ //We create the list of bean createList(); } private void createList(){ BeanList.clear(); for(int i = 0; i < 1000; i++){ bean = new MemoryBean(); bean.setField1("Field+1+("+i+")"); bean.setField2("Field+2+("+i+")"); bean.setField3("Field+3+("+i+")"); bean.setField4("Field+4+("+i+")"); bean.setField5("Field+5+("+i+")"); bean.setField6("Field+6+("+i+")"); bean.setField7("Field+7+("+i+")"); bean.setField8("Field+8+("+i+")"); bean.setField9("Field+9+("+i+")"); bean.setField10("Field+10+("+i+")"); bean.setField11("Field+11+("+i+")"); bean.setField12("Field+12+("+i+")"); bean.setField13("Field+13+("+i+")"); bean.setField14("Field+14+("+i+")"); bean.setField15("Field+15+("+i+")"); bean.setField16("Field+16+("+i+")"); bean.setField17("Field+17+("+i+")"); bean.setField18("Field+18+("+i+")"); bean.setField19("Field+19+("+i+")"); bean.setField20("Field+20+("+i+")"); bean.setField21("Field+21+("+i+")"); bean.setField22("Field+22+("+i+")"); bean.setField23("Field+23+("+i+")"); bean.setField24("Field+24+("+i+")"); bean.setField25("Field+25+("+i+")"); bean.setField26("Field+26+("+i+")"); bean.setField27("Field+27+("+i+")"); bean.setField28("Field+28+("+i+")"); BeanList.add(bean); } } public List<?> getBeans() { return BeanList; } }
Zul page:
<zk> <window title="LBMemory" border="normal" onCreate="@command('Start')" apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('org.sts.Pruebas.PruebasMemoria.ListBoxMemory')" height="100%"> <listbox id="Listbox" mold="paging" pagingPosition="bottom" span="true" autopaging="true" width="100%" height="100%" sizedByContent="true" vflex="true" model="@load(vm.beans)" > <template name="model" var="item"> <listitem value="@load(item)" > <listcell label="@load(item.field1)" ></listcell> <listcell label="@load(item.field2)" ></listcell> <listcell label="@load(item.field3)" ></listcell> <listcell label="@load(item.field4)" ></listcell> <listcell label="@load(item.field5)" ></listcell> <listcell label="@load(item.field6)" ></listcell> <listcell label="@load(item.field7)" ></listcell> <listcell label="@load(item.field8)" ></listcell> <listcell label="@load(item.field9)" ></listcell> <listcell label="@load(item.field10)" ></listcell> <listcell label="@load(item.field11)" ></listcell> <listcell label="@load(item.field12)" ></listcell> <listcell label="@load(item.field13)" ></listcell> <listcell label="@load(item.field14)" ></listcell> <listcell label="@load(item.field15)" ></listcell> <listcell label="@load(item.field16)" ></listcell> <listcell label="@load(item.field17)" ></listcell> <listcell label="@load(item.field18)" ></listcell> <listcell label="@load(item.field19)" ></listcell> <listcell label="@load(item.field20)" ></listcell> <listcell label="@load(item.field21)" ></listcell> <listcell label="@load(item.field22)" ></listcell> <listcell label="@load(item.field23)" ></listcell> <listcell label="@load(item.field24)" ></listcell> <listcell label="@load(item.field25)" ></listcell> <listcell label="@load(item.field26)" ></listcell> <listcell label="@load(item.field27)" ></listcell> <listcell label="@load(item.field28)" ></listcell> </listitem> </template> </listbox> </window> </zk>
The bean:
public class MemoryBean { //Var private String Field1 = ""; private String Field2 = ""; private String Field3 = ""; private String Field4 = ""; private String Field5 = ""; private String Field6 = ""; private String Field7 = ""; private String Field8 = ""; private String Field9 = ""; private String Field10 = ""; private String Field11 = ""; private String Field12 = ""; private String Field13 = ""; private String Field14 = ""; private String Field15 = ""; private String Field16 = ""; private String Field17 = ""; private String Field18 = ""; private String Field19 = ""; private String Field20 = ""; private String Field21 = ""; private String Field22 = ""; private String Field23 = ""; private String Field24 = ""; private String Field25 = ""; private String Field26 = ""; private String Field27 = ""; private String Field28 = ""; //Constructor public MemoryBean(){ } //Getters public String getField1() { return Field1; } public String getField2() { return Field2; } public String getField3() { return Field3; } public String getField4() { return Field4; } public String getField5() { return Field5; } public String getField6() { return Field6; } public String getField7() { return Field7; } public String getField8() { return Field8; } public String getField9() { return Field9; } public String getField10() { return Field10; } public String getField11() { return Field11; } public String getField12() { return Field12; } public String getField13() { return Field13; } public String getField14() { return Field14; } public String getField15() { return Field15; } public String getField16() { return Field16; } public String getField17() { return Field17; } public String getField18() { return Field18; } public String getField19() { return Field19; } public String getField20() { return Field20; } public String getField21() { return Field21; } public String getField22() { return Field22; } public String getField23() { return Field23; } public String getField24() { return Field24; } public String getField25() { return Field25; } public String getField26() { return Field26; } public String getField27() { return Field27; } public String getField28() { return Field28; } //Setters public void setField1(String field1) { Field1 = field1; } public void setField2(String field2) { Field2 = field2; } public void setField3(String field3) { Field3 = field3; } public void setField4(String field4) { Field4 = field4; } public void setField5(String field5) { Field5 = field5; } public void setField6(String field6) { Field6 = field6; } public void setField7(String field7) { Field7 = field7; } public void setField8(String field8) { Field8 = field8; } public void setField9(String field9) { Field9 = field9; } public void setField10(String field10) { Field10 = field10; } public void setField11(String field11) { Field11 = field11; } public void setField12(String field12) { Field12 = field12; } public void setField13(String field13) { Field13 = field13; } public void setField14(String field14) { Field14 = field14; } public void setField15(String field15) { Field15 = field15; } public void setField16(String field16) { Field16 = field16; } public void setField17(String field17) { Field17 = field17; } public void setField18(String field18) { Field18 = field18; } public void setField19(String field19) { Field19 = field19; } public void setField20(String field20) { Field20 = field20; } public void setField21(String field21) { Field21 = field21; } public void setField22(String field22) { Field22 = field22; } public void setField23(String field23) { Field23 = field23; } public void setField24(String field24) { Field24 = field24; } public void setField25(String field25) { Field25 = field25; } public void setField26(String field26) { Field26 = field26; } public void setField27(String field27) { Field27 = field27; } public void setField28(String field28) { Field28 = field28; } }
Action - Memory(KB)
Start - 48.748
2nd page - 51.992
14th page - 70.584
Return to 2nd page - 74.232
22nd page - 80.100
10 minutes past -80.172
Conclusion:
The memory usage by java process always rises when I paging and never decrease. Increase the server’s memory is the only way to solve it?
Please, I will be very grateful if we could solve this problem.
Thanks for all,
Regards,
Marky
I'm fighting against the same problem. I've tried loading listboxes with beans, without beans, with listmodel and renderer and the memory always increases very fast.
It's a big problem and I don't know how to solve it.
Thank you
have you tried zk object deletion from session?
Write something like this:
session.removeAttribute(org.zkoss.zk.ui.sys.Attributes.GAE_FIX);
session.removeAttribute(org.zkoss.zk.ui.sys.Attributes.ZK_SESSION);
session.removeAttribute("org.zkoss.zk.pi");
session.removeAttribute("javax.zkoss.ui.session.private");
session.removeAttribute("org.zkoss.zk.ui.sys.RequestCount");
Hi pinods!
I have tryed use this sentences but didn't work.
Session.removeAttribute(org.zkoss.zk.ui.sys.Attributes.GAE_FIX) and session.removeAttribute(org.zkoss.zk.ui.sys.Attributes.ZK_SESSION) close my session.
The others, session.removeAttribute("org.zkoss.zk.pi"); session.removeAttribute("javax.zkoss.ui.session.private"); and session.removeAttribute("org.zkoss.zk.ui.sys.RequestCount");
I'm watching the memory after add this sentences but they aren't any change.
Pinod, where you extract this code? I search it in ZK page but I can't find they.
Thanks for all, I will continue looking for the answer.
Regards,
Marky.
Hi Marky,
when surfing from a zk page to another, we don't free memory (used by objects of the previous page). And this is a problem: you think a page with a grid and 30k elements, then you change page clicking on a link to another page. Who free memory of the 30k elements grid?
I found that analizing used memory and session changes, and i remove that objects when i move from a page to another (without any problem); so a little explanation:
org.zkoss.zk.ui.sys.Attributes.GAE_FIX
A special attribute set to the session to cause Google App Engine to update attributes to the storage
org.zkoss.zk.ui.sys.Attributes.ZK_SESSION
javax.zkoss.ui.session.private A session attribute used to store the ZK session in the native session.
Are you using the ZK Session to store things right? If you want to release resources when you switch to another zul page --> use the Desktop...
Or maybe i've missed something of your scenario description? :)
Hi,
first, I use Session scope to save some data, but this is not the problem (we use session to keep the user as long as session).
Then, I understand that ZK doesn't clean the memory while I'm in the same page, but, why don't use the old objects instead creat the new objects?
I have other exemple where I have a list with 10 beans. This beans are binded on listbox and I pass the data from other list. In this exemple (is too easy to post it but if it's necesary I can do it) I only have 10 beans, there aren't more objects. When I paging this list i replace that beans with the next 10. Always I have only 10 rows in the listbox. And memory never stops increase.
Any idea?
Thanks, Marky.
never mind me: i have now read your long post carefully and honestly never had such a problem sorry! Have you tried to analyze the heap dump?
@pinods,
the memory increases while I paging the listbox, when I open a window, close it and then I open again, in summary, always. This is the exemple with 10 beans. the size of the binding list is always 10, accordingly the memory usage may be comparable with 10 objects.
This exemple has a paging to emulate the mold="paging".
Zul page:
<zk xmlns:n="native"> <borderlayout id = "BLGeneral" onCreate="@command('InicializaPagina')" onTest="@command('test')" apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('org.sts.Pruebas.PruebasListBoxDinamico.LBDinamico')"> <north border="none" id="Norte"> <listbox id="LBSeguimiento" nonselectableTags="" span="3,8" pagingPosition="bottom" autopaging="true" width="99.8%" sizedByContent="true" style="margin-top:4px;" vflex="true" onSelect="@command('SeleccionaFila')"model="@load(vm.beans2)" selectedItem="@bind(vm.beanSeleccionado)" onPaging="@command('pasarPagina')"> <listhead sizable="true"> <listheader width="33px"> <checkbox id="CKTodosSeleccionados" onCheck="@command('SeleccionarTodos', checked = self.checked)"></checkbox> </listheader> <listheader ></listheader> <listheader ></listheader> <listheader ></listheader> <listheader ></listheader> <listheader ></listheader> <listheader ></listheader> <listheader></listheader> <listheader></listheader> <listheader ></listheader> <listheader ></listheader> </listhead> <template name="model" var="item"> <listitem value="@load(item)" onDoubleClick="@command('DubleClick')" > <listcell style="text-align:center"> <checkbox></checkbox> </listcell> <listcell label="@load(item.field1)" ></listcell> <listcell label="@load(item.field2)" ></listcell> <listcell label="@load(item.field3)" ></listcell> <listcell label="@load(item.field4)" ></listcell> <listcell label="@load(item.field5)"></listcell> <listcell label="@load(item.field6)"></listcell> <listcell label="@load(item.field7)"></listcell> <listcell label="@load(item.field8)"></listcell> <listcell label="@load(item.field9)"></listcell> <listcell label="@load(item.field10)"></listcell> </listitem> </template> </listbox> <panel visible="true" height="25px" zclass="z-paging"> <panelchildren style="background:transparent; border:none"> <div style="float:left;"> <toolbarbutton id="TBTPrimeraPos" onClick="@command('Inicio')" style="margin-left:5px;"></toolbarbutton> <toolbarbutton id="TBTRetroceder" onClick="@command('Retroceder')" style="margin-left:5px"></toolbarbutton> <separator spacing="5px" orient="vertical"></separator> <textbox id="TBPagActual" width="50px" value="1" readonly="true"></textbox> <separator orient="vertical" spacing="1px"></separator> <label id="LBLTotalPaginas" value=" / 1"></label> <separator orient="vertical" spacing="5px"></separator> <toolbarbutton id="TBTAvanzar" onClick="@command('Avanzar')"></toolbarbutton> <toolbarbutton id="TBTUltimaPos" onClick="@command('Fin')" style="margin-left:5px;"></toolbarbutton> </div> <div style="float:right; margin-top:6px; color:gray"> <label id="LBLInfoPaginacion" value="[0 - 0 / 0]" style="float:right"></label> </div> </panelchildren> </panel> </north> </borderlayout> </zk>
The java class:
//Comands para enlazar con la capa de visualizacion @Command @NotifyChange("*") public void Avanzar(Event event){ Avanzar(listaBeansEnlace, listaBeansFiltrada,paginado); } @Command @NotifyChange("*") public void Retroceder(Event event){ Retroceder(listaBeansEnlace, listaBeansFiltrada,paginado); } @Command @NotifyChange("*") public void Fin(Event event){ ultimaPosicion(listaBeansEnlace, listaBeansFiltrada,paginado); } @Command @NotifyChange("*") public void Inicio(Event event){ primeraPosicion(listaBeansEnlace, listaBeansFiltrada,paginado); } //This are the methods that move the records /** * Dada una posicion en la listadBean pasada por parametro,anyade tantos beans como se haya indicado por parametro. Actualiza el paginado con los nuevos valores * @param listaBeansEnlace lista donde iran los beans para enlazar con la tabla de datos (el numero maximo de beans debe ser la altura del listbox, se pasa por parametro con numLineasPagina) * @param listaBean lista con todos los beans llenos de donde se extrae para llenar la lista de beansEnlace */ public static void Avanzar(List<?>listaBeansEnlace,List<?> listaBean,Paginado paginado){ //Comprobamos que se pueda avanzar if(paginado.getiPosIndiceRegistros()<listaBean.size()){ //Si vamos a avanzar limpiamos la lista listaBeansEnlace.clear(); int MaxLista = listaBean.size(); int i = paginado.getiPosIndiceRegistros(); // Seleccionamos del indice actual (iPosIndiceRegistros) + iPosicionesAvanzar. if(MaxLista==0){ MaxLista++; //No hay datos. // Actualizamos info de paginaciónZX // Nos guardamos el indice actual paginado.setiPosIndiceRegistros(0); // Actualizamos pagina actual paginado.setiPagActual(0); paginado.getLBLInfoPaginacion().setValue("[0 - 0 / 0]"); if(MaxLista<paginado.getNumLineasPagina()){ paginado.getLBLTotalPaginas().setValue(" / 1"); }else{ paginado.getLBLTotalPaginas().setValue(" / " + MaxLista / paginado.getNumLineasPagina()); } paginado.getTBPagActual().setValue(String.valueOf(paginado.getiPagActual() + 1)); }else{ if (paginado.getiPosIndiceRegistros() < MaxLista-1){ //El indice en el que se encuentra el unidynarray es más pequeño que el total de datos //Recorremos los registros desde el actual+1 hasta el actual + el número de lineas por pagina for ( i = paginado.getiPosIndiceRegistros()+1; i < paginado.getiPosIndiceRegistros() + paginado.getNumLineasPagina()+1; i++ ){ if (i<=MaxLista){ // Validación para que no se pase del total de registros try { CrearFila(i-1,listaBeansEnlace,listaBean); } catch (IOException e) { e.printStackTrace(); } }else{ //En caso de pasarse paramos el bucle para que la i no se vea afectada //Como se ha pasado de bucle restamos una iteracion a la i break; } } // Actualizamos info de paginación //(se muestran los registros desde el registro actual hasta el registro actual + las lineas que queire visualizar el usuario) paginado.getLBLInfoPaginacion().setValue("[" + (paginado.getiPosIndiceRegistros()+1 ) + " - " + (i-1) + " / " + (listaBean.size()) + "]"); if(MaxLista<paginado.getNumLineasPagina()){ paginado.getLBLTotalPaginas().setValue(" / 1"); }else{ //La función ceil redondea hacia arriba paginado.getLBLTotalPaginas().setValue(" / " + (int)Math.ceil( Double.valueOf(MaxLista) / Double.valueOf(paginado.getNumLineasPagina()) )); } paginado.getTBPagActual().setValue(String.valueOf(paginado.getiPagActual() + 1)); // Nos guardamos el indice actual(le quitamos dos, uno a razon de la i del bucle, que no ha llegado porque era con < y el otro a razon de que las listas parten desde 0 no desde 1) paginado.setiPosIndiceRegistros(i-1); // Actualizamos pagina actual paginado.setiPagActual(paginado.getiPagActual() + 1); } } } } /** * Muestra los anteriores numLineasPagina registros */ public static void Retroceder(List<?>listaBeansEnlace,List<?> listaBean,Paginado paginado){ //Capturamos el total de elementos para que no varie cuando se limpie la lista int itemsListbox = paginado.getLBSeguimiento().getItemCount(); // Seleccionamos del indice actual (iPosIndiceRegistros) - iPosicionesAvanzar. if (paginado.getiPosIndiceRegistros() - itemsListbox != 0){ //limpiamos la lista que vamos a asociar listaBeansEnlace.clear(); //Comprobamos si es la ultima pagina if(paginado.getiPagActual()!= (int) Math.ceil( Double.valueOf(listaBean.size()+1) / Double.valueOf(paginado.getNumLineasPagina()) )){ //No es la ultima pagina //Capturamos la posicion para el retroceso paginado.setiPosIndiceRegistros(paginado.getiPosIndiceRegistros()-paginado.getNumLineasPagina()); }else{ //Es la ultima pagina paginado.setiPosIndiceRegistros(paginado.getiPosIndiceRegistros() - itemsListbox); } // Actualizamos pagina actual paginado.setiPagActual(paginado.getiPagActual() - 1); // Actualizamos info paginado.getLBLInfoPaginacion().setValue("[" + ((paginado.getiPosIndiceRegistros()+1) - paginado.getNumLineasPagina()) + " - " + (paginado.getiPosIndiceRegistros()) + " / " + (listaBean.size()) + "]"); //La función ceil redondea hacia arriba paginado.getLBLTotalPaginas().setValue(" / " + (int) Math.ceil( Double.valueOf(listaBean.size()+1) / Double.valueOf(paginado.getNumLineasPagina()) )); paginado.getTBPagActual().setValue(String.valueOf(paginado.getiPagActual())); for (int i = paginado.getiPosIndiceRegistros()-paginado.getNumLineasPagina(); i < paginado.getiPosIndiceRegistros(); i++ ){ try { CrearFila(i,listaBeansEnlace,listaBean); } catch (IOException e) { e.printStackTrace(); } } } } public static void ultimaPosicion(List<?>listaBeansEnlace,List<?> listaBean,Paginado paginado){ int maxTamanyo = listaBean.size() + 1; if(maxTamanyo>paginado.getNumLineasPagina()){ //Miramos que la pagina actual no sea la ultima if(paginado.getiPagActual()!=(int) Math.ceil( Double.valueOf(maxTamanyo) / Double.valueOf(paginado.getNumLineasPagina()) )){ //Miramos que no acabe exacta la ultima pagina if(maxTamanyo%paginado.getNumLineasPagina()==0){ //No sobran lineas por pagina (el número de registros es multiplo de el número de lineas por pagina) paginado.setiPosIndiceRegistros(maxTamanyo -1); paginado.setiPagActual(maxTamanyo / (paginado.getNumLineasPagina()-1)); }else{ //La última pagina tiene menos registros que el número de lineas (el número de registros no es multiplo del numero de lineas por pagina) paginado.setiPosIndiceRegistros(maxTamanyo-((maxTamanyo-1)%paginado.getNumLineasPagina())-1); paginado.setiPagActual(maxTamanyo / paginado.getNumLineasPagina()); } Avanzar(listaBeansEnlace,listaBean,paginado); paginado.getLBSeguimiento().invalidate(); } } } public static void primeraPosicion(List<?>listaBeansEnlace,List<?> listaBean,Paginado paginado){ if(paginado.getiPagActual()!=1){ //No es la primera pagina paginado.setiPosIndiceRegistros(0); paginado.setiPagActual(0); Avanzar(listaBeansEnlace,listaBean,paginado); paginado.getLBSeguimiento().invalidate(); } } //This is the method that pass the bean from the original list to binding list /** * Anyade un bean de una posicion concreta de la lista de beans principal a la lista de beans que esta enlazada a la tabla de datos * @param posicion * @param listaBeansEnlace * @param listaBeans * @throws IOException */ @SuppressWarnings("unchecked") private static void CrearFila(int posicion, List listaBeansEnlace, List listaBeans) throws IOException{ listaBeansEnlace.add(listaBeans.get(posicion)); }
Paginado is an own class for handle the components of own paging(Toolbarbuttons and labels):
public class Paginado extends GenericForwardComposer<Component> { /** * */ private static final long serialVersionUID = 1L; private int iPosIndiceRegistros=0; private int iPagActual=0; private int numLineasPagina=0; private Label LBLInfoPaginacion; private Label LBLTotalPaginas; private Textbox TBPagActual; private Listbox LBSeguimiento; /** * Constructor de la clase. Permite asignar componentes y variables a las variables miembro de la clase * @param LBSeguimiento * @param TBPagActual * @param LBLTotalPaginas * @param LBLInfoPaginacion * @param numLineasPagina * @param iPagActual * @param iPosIndiceRegistros */ public Paginado(Listbox LBSeguimiento, Textbox TBPagActual, Label LBLTotalPaginas,Label LBLInfoPaginacion,int numLineasPagina,int iPagActual, int iPosIndiceRegistros ){ setLBSeguimiento(LBSeguimiento); setTBPagActual(TBPagActual); setLBLTotalPaginas(LBLTotalPaginas); setLBLInfoPaginacion(LBLInfoPaginacion); setNumLineasPagina(numLineasPagina); setiPagActual(iPagActual); setiPosIndiceRegistros(iPosIndiceRegistros); } public int getiPosIndiceRegistros() { return iPosIndiceRegistros; } public void setiPosIndiceRegistros(int iPosIndiceRegistros) { this.iPosIndiceRegistros = iPosIndiceRegistros; } public int getiPagActual() { return iPagActual; } public void setiPagActual(int iPagActual) { this.iPagActual = iPagActual; } public int getNumLineasPagina() { return numLineasPagina; } public void setNumLineasPagina(int numLineasPagina) { this.numLineasPagina = numLineasPagina; } public Label getLBLInfoPaginacion() { return LBLInfoPaginacion; } public void setLBLInfoPaginacion(Label lBLInfoPaginacion) { LBLInfoPaginacion = lBLInfoPaginacion; } public Label getLBLTotalPaginas() { return LBLTotalPaginas; } public void setLBLTotalPaginas(Label lBLTotalPaginas) { LBLTotalPaginas = lBLTotalPaginas; } public Textbox getTBPagActual() { return TBPagActual; } public void setTBPagActual(Textbox tBPagActual) { TBPagActual = tBPagActual; } public Listbox getLBSeguimiento() { return LBSeguimiento; } public void setLBSeguimiento(Listbox lBSeguimiento) { LBSeguimiento = lBSeguimiento; } public void reiniciarPaginado(){ iPosIndiceRegistros = 0; iPagActual = 0; }
Regards,
Marky
Hi
We had the same problem and we did the following to solve this issue:
1. Implement your own paging, do NOT use the paging of the listbox.
2. populate only the items you want to show in one page of the listbox. Use org.zkoss.zul.SimpleListModel as model for the listbox
In other words, if your page size is 20, always create a SimpleListModel which contains 20 model items, and use setModel of listbox to show those items.
With this approach, ZK has always only knowledge of 20 list items, and does not produce listitem objects for all model objects.
Regards,
Dieter
Asked: 2012-09-21 07:14:57 +0800
Seen: 696 times
Last updated: Oct 30 '12