Home » Archived » EGL Development Tools » How can I manage widget instances?
| |
Re: How can I manage widget instances? [message #881302 is a reply to message #878754] |
Mon, 04 June 2012 10:03 |
lu lu Messages: 9 Registered: June 2012 |
Junior Member |
|
|
Hi Sorry for the late response.
I investigate the Destory widget process in Gridlayout.
If you always use
ui.children = {new Box{..}} without located in any cell of GridLayout?
In initTable() method, children of table will be destoryed, I write a sample, not sure if what you required.
1. 'Button' & 'Box' are the children of ui.
2. When click 'Button', then the children of gridLayout will be 'change' widget only.
**************************************************
package client;
// RUI Handler
import org.eclipse.edt.rui.widgets.Box;
import org.eclipse.edt.rui.widgets.GridLayout;
import org.eclipse.edt.rui.widgets.GridLayoutData;
import org.eclipse.edt.rui.widgets.Button;
import dojo.widgets.DojoButton;
//
//
handler bb type RUIhandler{initialUI =[ui
], onConstructionFunction = start, cssFile = "css/v.css", title = ""}
ui GridLayout{columns = 3, rows = 4, cellPadding = 4, children = [ Button, Box ]};
Box Box{ layoutData = new GridLayoutData{ row = 3, column = 2 }, padding=8 };
change Button{ layoutData = new GridLayoutData{ row = 4, column = 2 }, text="Normal Button, Children of GridLayout" };
Button DojoButton{ layoutData = new GridLayoutData{ row = 4, column = 2 }, text = "Change Children", onClick ::= Button_onClick };
function start()
end
function Button_onClick(event Event in)
ui.children = [change];
end
end
******************************************************
If this is what you required, pls provide me some of your sample usage. Thanks.
|
|
|
Re: How can I manage widget instances? [message #881348 is a reply to message #881302] |
Mon, 04 June 2012 11:37 |
Richard Moulton Messages: 92 Registered: August 2011 Location: Devon, UK |
Member |
|
|
Hi,
I didn't fully understand what you were saying but below I've included a sample that illustrates my point/question.
The first source is for a main rui handler. This displays two buttons; one to add a new box child to my main handler, replacing the previous children and the second will publish an infobus request to the widget children asking them to say hello.
The second source is for my widget that will be added as a child of the main handler when the 'add box' button is pressed.
If you try this and then press the 'add box' n times and then press the 'say hello' button you will get a response from all of the added widgets, so they still exist.
My question revolves around the use of the following code, to add a child. By using this code it appears that I then unable to destroy that child widget.
container.children = [ new TestWidget{ height=100, width=100, backgroundColor=boxColour, children=[ new HTML{ text = "I am box number " :: boxNumber } ], boxNumber=boxNumber } ];
Is there a way I can destroy that child widget?
Is this behaviour expected?
Is there some method I should be using to manage new widget instances?
I hope that makes my question(s) clearer.
Richard
****************************************************
package client;
import org.eclipse.edt.rui.infobus.InfoBus;
import org.eclipse.edt.rui.widgets.Button;
import org.eclipse.edt.rui.widgets.Div;
import org.eclipse.edt.rui.widgets.HTML;
handler TestParent type RUIhandler{initialUI =[ui], onConstructionFunction = start, cssFile = "css/stocks.css", title = "TestParent"}
ui Div{children =[addboxButton, sayhiButton, container]};
container Div{ children=[] };
addboxButton Button{ text="Add Box",onClick::=addBox };
sayhiButton Button{ text="Say Hello",onClick::=sayHi };
boxNumber int = 0;
function start()
end
function addBox(e event in)
boxNumber += 1;
boxColour string;
case(boxNumber%3)
when(1)
boxColour = "Red";
when(2)
boxColour = "Blue";
otherwise
boxColour = "yellow";
end
container.removeChildren();
container.children = [
new TestWidget{ height=100, width=100, backgroundColor=boxColour,
children=[ new HTML{ text = "I am box number " :: boxNumber } ],
boxNumber=boxNumber } ];
end
function sayHi(e event in)
InfoBus.publish("SayHello", "Hello from box number ");
end
end
****************************************************
package client;
import org.eclipse.edt.rui.infobus.InfoBus;
import org.eclipse.edt.rui.widgets.Div;
handler TestWidget type RUIWidget{targetWidget = ui, onConstructionFunction = start, cssFile = "css/stocks.css", @VEWidget{category = "Custom"}}
ui Div{ children = [container] };
container Div{ children = [] };
boxNumber int;
function start()
InfoBus.subscribe("SayHello", SayHello_callback);
end
function setChildren(widgets widget[] in)
container.children = widgets;
end
function SayHello_callback(eventName string in, data any in)
sysLib.writeStdout(data as string :: boxNumber);
end
end
****************************************************
|
|
|
Re: How can I manage widget instances? [message #882097 is a reply to message #881348] |
Tue, 05 June 2012 21:01 |
Brian Svihovec Messages: 55 Registered: July 2009 |
Member |
|
|
Richard,
In your example, both the TestParent handler and the InfoBus Library are holding a pointer to your TestWidget handler, with TestParent holding a direct pointer to the TestWidget, and InfoBus holding an 'indirect' pointer via the callback function 'SayHello_callback'. When you reset the children of the container div in TestParent.addBox, you are breaking the link from TestParent to TestWidget, but the InfoBus is still holding this link as you have discovered.
In this situation, I believe you will either need to let the TestParent manage the subscribing and unsubscribing of the TestWidget with the InfoBus, or you will need to add a function to TestWidget that you can invoke from TestParent to 'cleanup' the TestWidget when it is no longer needed. Once an object is no longer being referenced by any other objects, the JavaScript garbage collector will automatically reclaim the memory associated with the object.
It is also worth mentioning that in addition to managing the InfoBus subscription, you will also need to tell the Rich UI runtime framework that a widget is no longer needed, so that the DOM elements associated with the widget can be discarded. To do this in your example, I believe you will need to do something like the following:
theChildren Widget[] = container.children; // hold onto the children
container.removeChildren(); // remove them from the container
for(i int from 1 to theChildren.getSize())
UtilLib.destroyWidget(theChildren[i]); // destroy the children
end
Invoking destroyWidget is necessary because some older browsers are unable to reclaim the memory of JavaScript objects that are holding references to the DOM tree, which can cause a memory leak if the browser window is refreshed since all of the widget objects cannot be reclaimed. To work around this issue, the Rich UI Runtime keeps track of all widgets that are created and automatically destroys them when the application is terminated. During the destroy process, all of the DOM elements associated with the widget, and its children, are separated from their corresponding JavaScript objects so that the memory can be reclaimed.
If an application creates and discards widgets as part of its normal processing, these discarded widgets will appear as memory leaks in the runtime until the application is terminated. An alternative to invoking destroy in this situation is to re-use as many widget instances as possible, instead of creating new widgets, but in some cases it may be necessary for a widget to be destroyed using the UtilLib functions.
-Brian
|
|
| | | |
Re: How can I manage widget instances? [message #883056 is a reply to message #882578] |
Thu, 07 June 2012 18:53 |
Brian Svihovec Messages: 55 Registered: July 2009 |
Member |
|
|
Richard,
OpenAjax.hub._subscriptions maintains the subscriptions that you are manually defining in your application when using InfoBus.subscribe(), and it is important that you unsubscribe any widgets that you are no longer using so that they can be garbage collected.
Any elements that you create are also automatically added to the egl.elements array by the Rich UI runtime when they are created, and are only removed from this array when the application is terminated or when UtilLib.destroyWidget() is invoked.
In general, a widget can only be garbage collected by the browser when it is no longer being referenced by the application. All widgets that are no longer being used should be destroyed using UtilLib.destoryWidget(), but before destoryWidget is invoked, "manual" references to these widgets should also be removed from the application, which could include InfoBus subscriptions, storage in an array of another widget or handler, etc.
In the future, it would be best if the Rich UI Runtime can be updated to automatically invoke destroyWidget on elements of the array that are no longer being referenced by an application, but for now this has to be invoked manually.
-Brian
|
|
| | |
Goto Forum:
Current Time: Thu Dec 26 11:29:12 GMT 2024
Powered by FUDForum. Page generated in 0.04354 seconds
|