As a part of trying to tackle a memory leak in our application, we discovered that for every SkinnableComponent
, the skinDestructionPolicy
is set to "never"
by default.
This means that when using static skin parts, the skin is forever detained in memory.
Furthermore, the override of a partRemoved() in the host component will never be triggered.
Hence, event listeners we add in the partAdded() override are not removed, which effectively causes views and skins to be kept in memory.
When doing a lot of view switches this is just not acceptable.
Here is an example of of how we are working around this now:
public class ViewA extends SkinnableComponent
{
[SkinPart(required = "true")]
public var labelA:Label;
[SkinPart(required = "true")]
public var buttonA:Button;
public function ViewA()
{
super();
mx_internal::skinDestructionPolicy = 'auto';
}
override protected function getCurrentSkinState():String
{
return super.getCurrentSkinState();
}
override protected function partAdded(partName:String, instance:Object):void
{
super.partAdded(partName, instance);
trace("ViewA::partAdded " + partName);
if (instance == buttonA)
{
buttonA.addEventListener(MouseEvent.CLICK, buttonClickedHandler);
}
}
override protected function partRemoved(partName:String, instance:Object):void
{
trace("ViewA::partRemoved " + partName);
if (instance == buttonA)
{
buttonA.removeEventListener(MouseEvent.CLICK, buttonClickedHandler);
}
super.partRemoved(partName, instance);
}
override public function stylesInitialized():void
{
setStyle("skinClass", ViewASkin);
}
}
However, using the mx::internal
way to circumvent this behavior seems rather odd to me.
Documentation about this is scarce as well, so any ideas will be very welcome.
Cheers
In my experience the usage of the
mx::internal
namespace in the Flex SDK usually means something along the lines of: "you can use this functionality, if you know what you're doing, and also we (Adobe, or the Apache community in the future) don't guarantee that this API will never change in future versions of Flex".So there's no real issue with its usage, unless you're very concerned with backwards compatibility. If you really want to avoid using it, you can always just implement the behavior of
skinDestructionPolicy="auto"
in your subclass. There's not that much code to write:Note that in the
SkinnableComponent
class these two event listeners are attached (or not, depending on the policy) in thecommitProperties()
method. I moved that to theinitialize()
method because we don't need to check for changes in theskinDestructionPolicy
property anymore.Also note that this solution might cause an error if one did set
mx::internal skinDestructionPolicy
to"auto"
alongside.