Sorry, I didn't read the previous posts before I sent mine. Yes, Todd is correct in his brief summary.
Again, I'm wary of initialize(), not only because of the remove problem, but the clarity of when it's called. Since it is after serialization, then "constructed" (or similar) would be more appropriate. You are less likely to get into the dangling listener issue since there's nothing around to add to at that point. I do like Flex's model when we get around to defining one. :-) Without a component model component development can become a real hairball. In Swing, I've always bolted on my own. Michael Bushe Software Architect/Developer [email protected] www.bushe.com On Thu, Dec 31, 2009 at 9:00 AM, Michael Bushe <[email protected]> wrote: > Yes, listenerlist.remove() is how the listener is removed. The question > is: When is the listener removed? > > Let's say during initialize, the onInitialize() method finds the button's > window and adds itself as a listener to one of the windows' listener lists, > maybe to save some state when the window closes. Let's also say that the > button is added to a tab that can be closed (like Firefox). Without doing > anything else, if the user closes the tab, the button is going to go away - > almost. Since the window's listener list will still have a reference to the > button, the button will stay around forever. I'm describing the classic > Swing memory leak. Not only is there a small resource problem, but when the > window closes, the button will still be called and try to save some state, > even though it's probably not supposed to since as far is the user is > concerned, it's supposed to be gone. > > The initialize call is defining a component lifecycle, like it or not, and > I know of no proper lifecycles that have a start without a stop or an add > without a remove. There's another problem too - when is initialized > called? The name doesn't tell me exactly. Is it just after the button's > constructor? After the button is added the first time to it's container? If > it's after construction, then the window couldn't be found anyway, and > neither could any other component that the button itself does not create. > Does this also mean that in order to add a listener to another component in > initialize that all the subcomponents need to be instantiated in the > constructor? Isn't doing a lot of work in the constructor considered a bad > practice in Java? Yes, this adds complexity, but initialize() without > anything else is like trying to take a small sip from the 5 gallon jug you > are tipping into your mouth. > > If you want something in 1.4, or don't want to define a component > lifecycle, I suggest renaming "initialize" to "constructed" or > "postConstuction" to make it clear when it happens and to not conflict with > the use of some future lifecycle methods or events that is almost sure to > include "initialize" or "init." > > > Michael Bushe > Software Architect/Developer > [email protected] > www.bushe.com > > > On Wed, Dec 30, 2009 at 9:30 PM, Greg Brown <[email protected]> wrote: > >> Listeners can be removed by calling the remove() method on the listener >> list, similar to Swing and WPF. >> >> On Dec 30, 2009, at 9:26 PM, Michael Bushe wrote: >> >> > Greg, >> > >> > How/when can event listeners be removed (to avoid "memory >> leaks"/"loitering >> > objects")? Flex has a robust component lifecycle, I don't remember >> Pivot >> > having a component lifecycle model at all (and neither does Swing, >> except >> > for Window, you have to bolt it on yourself). I think I'd rather see >> the >> > whole model at once, I suppose in 1.5. >> > >> > I'm a HUGE fan of what you are trying to do, but maybe it should wait? >> > OTOH, you know you are going to have initialize(), maybe that's a good >> > start. On the third hand, if you add preInitialize() later (like Flex), >> > then existing initialize() calls aren't broken exactly, but when things >> > happen may shift and be a surprise. >> > >> > Michael Bushe >> > Software Architect/Developer >> > [email protected] >> > www.bushe.com >> > >> > >> > On Wed, Dec 30, 2009 at 9:14 PM, Greg Brown <[email protected]> wrote: >> > >> >> FYI, though it wasn't mentioned in the commit message, this change also >> >> included a minor addition/change to the org.apache.pivot.wtkx package. >> This >> >> change is relatively insubstantial but should actually have a >> significant >> >> impact on "real" application development. >> >> >> >> Some background: In Flex, MXML files are compiled to classes. So, this >> file >> >> generates a class named MyVBox: >> >> >> >> MyVBox.mxml: >> >> >> >> <mx:VBox initialize="onInitialize()" >> >> xmlns:mx="http://www.adobe.com/2006/mxml"> >> >> <mx:Script> >> >> public function onInitialize():void { >> >> // Wire up event handlers, etc. >> >> } >> >> >> >> public function onMyButtonClick():void { >> >> // Respond to button click >> >> } >> >> </mx:Script> >> >> >> >> <mx:Button id="myButton" label="Click Me" >> click="onMyButtonClick()"/> >> >> </mx:VBox> >> >> >> >> I can then use that class as a component in other MXML files (for >> example, >> >> I could add it to a tab pane, or "TabNavigator" in Flex). >> >> >> >> In Pivot, something similar could be done with the following WTKX: >> >> >> >> my_box_pane.wtkx: >> >> >> >> <BoxPane orientation="vertical" >> >> xmlns:wtkx="http://pivot.apache.org/wtkx" >> >> xmlns="org.apache.pivot.wtk"> >> >> <wtkx:script> >> >> function myButtonClicked() { >> >> // Respond to button click >> >> } >> >> </wtkx:script> >> >> >> >> <PushButton wtkx:id="myButton" buttonData="Click Me" >> >> ButtonPressListener.buttonPressed="myButtonClicked()"/> >> >> </BoxPane> >> >> >> >> We can then include my_box_pane.wtkx into a TabPane declared in another >> >> WTKX file. However, Pivot didn't have an equivalent of onInitialize(). >> If >> >> the root element is a Window, we could listen for windowOpened(), but >> >> otherwise we're stuck. >> >> >> >> Also, it becomes more complex when we want to associate Java code with >> WTKX >> >> includes, rather than putting the logic in script. This is something >> any >> >> non-trivial application is going to want to do, and Pivot didn't >> provide an >> >> easy way to do it. The change I checked in attempts to solve these two >> >> problems. We can't use WTKX to define new classes, but we can use WTKX >> to >> >> instantiate classes we have defined elsewhere. For example: >> >> >> >> MyBoxPane.java: >> >> >> >> public class MyBoxPane extends BoxPane implements Bindable { >> >> @WTKX private PushButton myButton = null; >> >> >> >> public MyBoxPane() { >> >> super(Orientation.VERTICAL); >> >> } >> >> >> >> @Override >> >> public void initialize() { >> >> myButton.getButtonPressListeners().add(new >> ButtonPressListener() >> >> { >> >> public void buttonPressed(Button button) { >> >> // Respond to button click >> >> } >> >> }); >> >> } >> >> } >> >> >> >> Using this approach, the updated my_box_pane.wtkx would look like this: >> >> >> >> my_box_pane.wtkx: >> >> >> >> <foo:MyBoxPane orientation="vertical" >> >> xmlns:wtkx="http://pivot.apache.org/wtkx" >> >> xmlns:foo="com.foo" >> >> xmlns="org.apache.pivot.wtk"> >> >> <PushButton wtkx:id="myButton" buttonData="Click Me"/> >> >> </foo:MyBoxPane> >> >> >> >> Once WTKXSerializer is done processing foo:MyBoxPane, it sees that it >> >> implements Bindable and bind()s to it. It then calls initialize() to >> allow >> >> the class to register event listeners and perform any other required >> >> initialization tasks. >> >> >> >> This is a late-breaking change for 1.4, so please let me know ASAP if >> you >> >> have any questions or concerns. >> >> >> >> G >> >> >> >> >> >> >
