|
Replies:
11
-
Last Post:
Jul 18, 2008 3:28 AM
by: cinsulan
|
|
|
|
|
|
|
Forms and Components
Posted:
Jul 17, 2008 6:53 AM
|
|
|
Hello all there,
I'm having some strange issues which make me think about how Forms an Components are related.
I have something similar to this:
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import com.sun.lwuit.Command;
import com.sun.lwuit.Display;
import com.sun.lwuit.Form;
import com.sun.lwuit.Label;
import com.sun.lwuit.events.ActionEvent;
import com.sun.lwuit.events.ActionListener;
public class Testing extends MIDlet implements ActionListener {
protected void startApp() throws MIDletStateChangeException {
Display.init(this);
showFirstScreen();
}
Label label = new Label("Hey There");
public void showFirstScreen() {
Form form = new Form() {
public void keyPressed(int keyCode) {
showSecondScreen();
}
};
form.addComponent(label);
form.show();
}
public void showSecondScreen() {
Form form = new Form() {
public void keyPressed(int keyCode) {
showFirstScreen();
}
};
form.addCommand(new Command("back", 0));
form.setCommandListener(this);
form.addComponent(new Label("2nd screen"));
form.show();
}
public void actionPerformed(ActionEvent event) {
switch (event.getCommand().getId()) {
case 0:
showFirstScreen();
break;
}
}
protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
}
protected void pauseApp() {
}
}
The thing is, the Label in first screen is a global variable. When I click any key, I swicth to second screen. From there, if I press back Command first screen is created again.
Why it says that the Component (Label) is already in the Container if the Container is a local variable. When will it be out of scope then?
In other words: I have a global Component and want to add to a local form. Probably later i will be adding the same Component to same but new instatiated local form. Is there anything I'm missing? How to release the Component from the Container? I thought setting the Container to null would do the trick, but no. In fact if I ask the newly created Form if he has the global Label Component, he returns a -1 (getComponentIndex(Component)) indicating the Component is not associated to the Form (sure, it's a new instance), but anyway I can't addComponent() if I don't remove it first.
Any advice, please?
|
|
|
|
|
|
|
Re: Forms and Components
Posted:
Jul 17, 2008 6:53 AM
in response to: kawaiimomo
|
|
|
|
|
Hi Kawaiimomo, In a component tree type widget system such as Swing/AWT, LWUIT etc... every component has a pointer to its parent which you can access using Component.getParent().
Since this is the case the previous form was never garbage collected although it was out of scope so the label wasn't removed. Java (and LWUIT) has no way of detecting that the Form is no longer used by yourself. We generally recommend to avoid components as class members and make sure to set them to null when leaving the scope (as we practice in the LWUIT Demo).
Thanks, Shai.
> Hello all there, > > I'm having some strange issues which make me think about how Forms > an Components are related. > > I have something similar to this: > > > import javax.microedition.midlet.MIDlet;
> import javax.microedition.midlet.MIDletStateChangeException;
>
> import com.sun.lwuit.Command;
> import com.sun.lwuit.Display;
> import com.sun.lwuit.Form;
> import com.sun.lwuit.Label;
> import com.sun.lwuit.events.ActionEvent;
> import com.sun.lwuit.events.ActionListener;
>
> public class Testing extends MIDlet implements ActionListener {
>
> protected void startApp() throws MIDletStateChangeException {
> Display.init(this);
> showFirstScreen();
> }
>
>
> Label label = new Label("Hey There");
> public void showFirstScreen() {
> Form form = new Form() {
> public void keyPressed(int keyCode) {
> showSecondScreen();
> }
> };
>
> form.addComponent(label);
>
> form.show();
> }
>
> public void showSecondScreen() {
> Form form = new Form() {
> public void keyPressed(int keyCode) {
> showFirstScreen();
> }
> };
>
> form.addCommand(new Command("back", 0));
> form.setCommandListener(this);
> form.addComponent(new Label("2nd screen"));
>
> form.show();
> }
>
> public void actionPerformed(ActionEvent event) {
> switch (event.getCommand().getId()) {
> case 0:
> showFirstScreen();
> break;
> }
> }
>
> protected void destroyApp(boolean arg0) throws
> MIDletStateChangeException {
> }
>
> protected void pauseApp() {
> }
> }
>
> > The thing is, the Label in first screen is a global variable. When > I click any key, I swicth to second screen. From there, if I press > back Command first screen is created again. > > Why it says that the Component (Label) is already in the Container > if the Container is a local variable. When will it be out of scope > then? > > In other words: I have a global Component and want to add to a > local form. Probably later i will be adding the same Component to > same but new instatiated local form. Is there anything I'm missing? > How to release the Component from the Container? I thought setting > the Container to null would do the trick, but no. In fact if I ask > the newly created Form if he has the global Label Component, he > returns a -1 (getComponentIndex(Component)) indicating the > Component is not associated to the Form (sure, it's a new > instance), but anyway I can't addComponent() if I don't remove it > first. > > Any advice, please? > [Message sent by forum member 'kawaiimomo' (kawaiimomo)] > > http://forums.java.net/jive/thread.jspa?messageID=287305 > > --------------------------------------------------------------------- > To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net > For additional commands, e-mail: users-help@lwuit.dev.java.net >
Shai Almog http://lwuit.blogspot.com/
[att1.html]
|
|
|
|
|
|
|
|
Re: Forms and Components
Posted:
Jul 17, 2008 10:59 PM
in response to: Shai Almog
|
|
|
Shai,
I find this statement somewhat peculiar.
"We generally recommend to avoid components as class members and make sure to set them to null when leaving the scope (as we practice in the LWUIT Demo)."
Are you saying that you consider having components as class members is bad practice or just "be careful" when you do so?
Edit: Isn't the above example an extreme because the label is actually member of he Midlet and not a separate form?
Having components as class members is most convenient when having to set their values at regular intervals. Of course, one could create runnables as members and use them together with member variables to updated their values, but it would be messy code in my opinion.
I assume the garbage collection works the same way as in j2se i.e. from the root component, if there are no references to another component, it will be removed. I have a form manager that keeps track of all forms using a hashtable for references. Assuming that is the only reference to a form, removing it should allow that form to be garbage collected, no?
Thankful for a reply.
Claes
Message was edited by: cinsulan
Message was edited by: cinsulan
|
|
|
|
|
|
|
|
Re: Forms and Components
Posted:
Jul 17, 2008 11:02 PM
in response to: cinsulan
|
|
|
|
|
Hi Claes, garbage collection works the same as in Java SE for Java ME. Garbage management works the same for LWUIT as it does for Swing.
Since a component in LWUIT has a reference to its parent, if the component won't be collected neither would its parent all the way up to the containing form.
This is easy to solve by one of the following strategies:
1. Rather than keep a class member keep a final variable for inner classes: void myMethod() { final Button b = new Button(...); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { // do something with b } }); }
in this case the button will be collected as you would expect.
2. When leaving the form/dialog just set component members to null to remove their reference. Recreate them as necessary: public void actionPerformed(ActionEvent ev) { // navigating out of screen componentUsedInScreen =null; }
3. Remove component from parent when navigating outside of the screen: public void actionPerformed(ActionEvent ev) { // navigating out of screen if(componentUsedInScreen != null) { componentUsedInScreen.getParent().removeComponent (componentUsedInScreen); } }
4. Rely on the source value of the action performed method (won't work for commands): void myMethod() { List l = new List(...); l.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { List l = (List)ev.getSource(); // do something with l } }); }
We use the first approach where possible in the LWUIT demo and sometimes the 3rd/2nd approach (depending on the case). This is essential for smaller and memory limited devices that we GC as much as possible, recreating a form/component is relatively cheap!
I also blogged a bit about memory issue tracking here: http://lwuit.blogspot.com/2008/06/memory-leaks-in-lwuit-and- tracking.html
> "We generally recommend to avoid components as class members > and make sure to set them to null when leaving the scope (as we > practice in the LWUIT Demo)." > > Are you saying that you consider this bad practice or just "be > careful"?
Like I said we keep a reference in the class member ourselves see the LWUIT Demo's RenderingDemo.cleanup() code to see what I mean. The bad practice is not cleaning up when you leave a form, the GC is powerful but if you keep a reference to something it just can't remove it.
> Having components as class members is most convenient when having > to set their values at regular intervals. Of course, one could > create runnables as members and use them together with member > variables to updated their values, but it would be messy code in my > opinion.
Sure but you don't need a reference to them when they are not on the screen. You could afford this "wastefulness" in Swing (which also has the exact same behavior) but you can't afford it in a S40 device.
Thanks,
Shai Almog http://lwuit.blogspot.com/
[att1.html]
|
|
|
|
|
|
|
|
Re: Forms and Components
Posted:
Jul 18, 2008 12:37 AM
in response to: Shai Almog
|
|
|
Hi,
Thanks a lot for the nice explanation and the info 
In my case, the class member is a MediaComponent and it's very likely the user would return again to that screen many times, so I thought it was better in terms of memory to declare it global and only initialize the player and create the MediaComponent only once.
Do you think is better this way and removing the reference to its parent when leaving the Form, or better create a new final instance of MediaComponent every time the user goes to that screen?
The problem I found in this final variable approach is that everytime the method is called it needs to create a new instance of a Player in order to be able to create a new MediaComponent(myPlayer), because creating the MediaComponent implies inner calls to Player.initDisplayMode and so on and this ends with an Exception saying it has been already initialized. Besides all this, the Player instance should be final too in order to be able to call Player.stop() when leaving the screen.
I guess creating new instances everytime the user wants to take a snapshot derives in high memory usage. In the other hand I only need to keep 2 global instances. So what do you guys recommend in this scenario?
Best Regards.
PS: Sorry if I went a little off topic
|
|
|
|
|
|
|
|
Re: Forms and Components
Posted:
Jul 18, 2008 12:37 AM
in response to: kawaiimomo
|
|
|
|
|
Hi, > In my case, the class member is a MediaComponent and it's very > likely the user would return again to that screen many times, so I > thought it was better in terms of memory to declare it global and > only initialize the player and create the MediaComponent only once.
Chen is a bigger expert than myself in the media dept. so he might be able to contribute a better strategy here. AFAIK you are correct, realizing a media file might be lengthy so it might be a good idea to cache the component. So the strategy of removing it from the parent component (thus allowing the form to GC) might be better. It might also be OK to leave this form always and never recreate it... We do this in LWUIT demo for the home screen which contains many icons in 3 different states, so we just keep the form always in memory and avoid the penalty of recreating it (while paying in memory overhead).
> I guess creating new instances everytime the user wants to take a > snapshot derives in high memory usage. In the other hand I only > need to keep 2 global instances. So what do you guys recommend in > this scenario?
If you have only one such form it might be reasonable to keep it in memory. I would run on the S40 emulator (enable its memory diagnosis option) and see the overhead, if you can work there then you are in reasonably good shape.
> PS: Sorry if I went a little off topic 
This is not off topic!! 
Thanks. Shai Almog http://lwuit.blogspot.com/
[att1.html]
|
|
|
|
|
|
|
|
Re: Forms and Components
Posted:
Jul 18, 2008 1:02 AM
in response to: Shai Almog
|
|
|
Thanks again Shai, for the good work and kind responses. Really appreciated.
I'm trying with creating new instances everytime and works well in terms of memory and speed. But you are right, it's a better idea to keep the whole form in memory.
Many Thanks!
|
|
|
|
|
|
|
|
Re: Forms and Components
Posted:
Jul 18, 2008 12:41 AM
in response to: Shai Almog
|
|
|
On Fri, Jul 18, 2008 at 8:02 AM, Shai Almog <Shai.Almog@sun.com> wrote: > Hi Claes, > garbage collection works the same as in Java SE for Java ME. > Garbage management works the same for LWUIT as it does for Swing. > Since a component in LWUIT has a reference to its parent, if the component > won't be collected neither would its parent all the way up to the containing > form.
I don't get this one, won't the class member Components + the form be garbage collected when the form is not accessible any more? Shouldn't this sentence be the other way round: "If the form won't be collected neither would its member Components"?
-- http://www.somatik.be Microsoft gives you windows, Linux gives you the whole house.
--------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net For additional commands, e-mail: users-help@lwuit.dev.java.net
|
|
|
|
|
|
|
|
Re: Forms and Components
Posted:
Jul 18, 2008 1:09 AM
in response to: Francis De Brab...
|
|
|
|
|
>> Hi Claes, >> garbage collection works the same as in Java SE for Java ME. >> Garbage management works the same for LWUIT as it does for Swing. >> Since a component in LWUIT has a reference to its parent, if the >> component >> won't be collected neither would its parent all the way up to the >> containing >> form. > > I don't get this one, won't the class member Components + the form be > garbage collected when the form is not accessible any more? Shouldn't > this sentence be the other way round: "If the form won't be collected > neither would its member Components"?
Hi Francis, There are no more references to the form but there are references to the component consider this:
private Button myButton;
private void calledOnStartup() { Form myForm = new Form(....); myButton = new Button(...); myForm.addComponent(myButton); myButton.addActionListener(...); myForm.show(); }
private void calledOnButtonPress() { new Form("Empty").show(); }
After pressing the button myForm is no longer reachable from Display.getInstance().getCurrent() and thus is supposedly ready for GC (garbage). However, it is reachable by invoking: myButton.getParent().getParent();
(first getParent() will return the content pane). This essentially prevents the garbage collector from reclaiming it because the component is still reachable in the class scope.
Thanks.
Shai Almog http://lwuit.blogspot.com/
[att1.html]
|
|
|
|
|
|
|
|
Re: Forms and Components
Posted:
Jul 18, 2008 1:17 AM
in response to: Shai Almog
|
|
|
Now I see how you get there, I'm always extending forms in my application so the components are always member of the form and not some other class.
class BlaForm extends Form{ private Button myButton; .... }
Is this a bad design form mobile dev?
On Fri, Jul 18, 2008 at 10:09 AM, Shai Almog <Shai.Almog@sun.com> wrote: > > Hi Claes, > garbage collection works the same as in Java SE for Java ME. > Garbage management works the same for LWUIT as it does for Swing. > Since a component in LWUIT has a reference to its parent, if the component > won't be collected neither would its parent all the way up to the containing > form. > > I don't get this one, won't the class member Components + the form be > garbage collected when the form is not accessible any more? Shouldn't > this sentence be the other way round: "If the form won't be collected > neither would its member Components"? > > Hi Francis, > There are no more references to the form but there are references to the > component consider this: > private Button myButton; > private void calledOnStartup() { > Form myForm = new Form(....); > myButton = new Button(...); > myForm.addComponent(myButton); > myButton.addActionListener(...); > myForm.show(); > } > private void calledOnButtonPress() { > new Form("Empty").show(); > } > > After pressing the button myForm is no longer reachable from > Display.getInstance().getCurrent() and thus is supposedly ready for GC > (garbage). > However, it is reachable by invoking: > myButton.getParent().getParent(); > (first getParent() will return the content pane). > This essentially prevents the garbage collector from reclaiming it because > the component is still reachable in the class scope. > Thanks. > Shai Almog > http://lwuit.blogspot.com/ >
-- http://www.somatik.be Microsoft gives you windows, Linux gives you the whole house.
--------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net For additional commands, e-mail: users-help@lwuit.dev.java.net
|
|
|
|
|
|
|
|
Re: Forms and Components
Posted:
Jul 18, 2008 1:28 AM
in response to: Francis De Brab...
|
|
|
|
|
If you extend form this shouldn't be a problem since the reference to myButton will be gone when you show() the next form. So this shouldn't be a problem.
Thanks, Shai.
> Now I see how you get there, I'm always extending forms in my > application so the components are always member of the form and not > some other class. > > class BlaForm extends Form{ > private Button myButton; > .... > } > > Is this a bad design form mobile dev? > > On Fri, Jul 18, 2008 at 10:09 AM, Shai Almog <Shai.Almog@sun.com> > wrote: >> >> Hi Claes, >> garbage collection works the same as in Java SE for Java ME. >> Garbage management works the same for LWUIT as it does for Swing. >> Since a component in LWUIT has a reference to its parent, if the >> component >> won't be collected neither would its parent all the way up to the >> containing >> form. >> >> I don't get this one, won't the class member Components + the form be >> garbage collected when the form is not accessible any more? Shouldn't >> this sentence be the other way round: "If the form won't be collected >> neither would its member Components"? >> >> Hi Francis, >> There are no more references to the form but there are references >> to the >> component consider this: >> private Button myButton; >> private void calledOnStartup() { >> Form myForm = new Form(....); >> myButton = new Button(...); >> myForm.addComponent(myButton); >> myButton.addActionListener(...); >> myForm.show(); >> } >> private void calledOnButtonPress() { >> new Form("Empty").show(); >> } >> >> After pressing the button myForm is no longer reachable from >> Display.getInstance().getCurrent() and thus is supposedly ready >> for GC >> (garbage). >> However, it is reachable by invoking: >> myButton.getParent().getParent(); >> (first getParent() will return the content pane). >> This essentially prevents the garbage collector from reclaiming it >> because >> the component is still reachable in the class scope. >> Thanks. >> Shai Almog >> http://lwuit.blogspot.com/ >> > > > > -- > http://www.somatik.be > Microsoft gives you windows, Linux gives you the whole house. > > --------------------------------------------------------------------- > To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net > For additional commands, e-mail: users-help@lwuit.dev.java.net >
Shai Almog http://lwuit.blogspot.com/
[att1.html]
|
|
|
|
|
|
|
|
Re: Forms and Components
Posted:
Jul 18, 2008 3:28 AM
in response to: Shai Almog
|
|
|
Shai,
Great work and thanks! Your last explanation explains why I misunderstood the initial explanation. I also only extend forms and keep members within the form making the form reference crucial for GC, but not the components. I almost thought I had a mem leak...
|
|
|
|
|