Flex: Memory Problem - apache-flex

I have problem on deleting component which is created on runtime. Please help me.
heres my code in creating component
var oh: ObjectHandles = new ObjectHandles;
oh.x = event.localX-xOff;
oh.y = event.localY-yOff;
Canvas(event.target).addChild(oh);
oh.addEventListener(KeyboardEvent.KEY_DOWN,deleteSel);
oh.width=270;
oh.height=200;
oh.mouseChildren = true;
var vdo:FXVideo = new FXVideo;
vdo.source = "http://thehq.tv/wp-content/uploads/flv/funny-people-trailer.flv";
vdo.percentHeight = 100;
vdo.percentWidth = 100;
oh.addChild(vdo);
code in keyboard delete event
private function deleteSel(event:KeyboardEvent):void
{
if(event.charCode == 127)
{
FXVideo(ObjectHandles(event.target).getChildAt(0)).stop();
delete(ObjectHandles(event.target).getChildAt(0));
ObjectHandles(event.target).removeAllChildren();
ObjectHandles(event.target).parent.removeChild(ObjectHandles(event.target));
delete ObjectHandles(event.target);
}
}
after I delete the Object Handles Component(inside is FxVideo Component) the memory usage is still there. How to remove the memory allocation of component after deletion?

You need to remove the event listener, or you can add the event listener with a weak reference:
oh.addEventListener(KeyboardEvent.KEY_DOWN,deleteSel,false,0,true)
I would not recommend calling delete. Calling removeAllChildren should take care of it. Although, by looking at your code, that probably is not necessary either. Once you remove the event listener it should get cleaned up.

delete only works with dynamic objects and won't have an affect here. I personally recommend explicitly removing the event listener:
event.target.removeEventListener(KeyboardEvent.KEY_DOWN,deleteSel);
as well as using the weak reference suggested by Osman.

Related

Meteor - Reactive Objects/Classes

TLDR
I like to really focus on keeping business logic away from the view model / controller. I find this sometimes rather hard in Meteor. Maybe I'm missing the point but I am after one of two things really:
1) A really good document explaining at a really low level how reactive values are being used.
2) A package that somehow manages an object so that if any of the setters are altered, they notify all of the get functions that would change as a result.
Unfortunately I've not seen either.
My Example
I have a fair bit ob business logic sitting behind a dialog used to document a consultation. I might have an event that sets a change of state.
I'd like to do something like this in the event:
const cc = new ConsultationEditor();
cc.setChiefComplaint(event.target.value);
console.log(cc.data());
ConsultationDict.set("consEdit", cc.data() );
When the user has updated this value, I'd then like to show a number of fields, based on the change. For this I have a helper with the following:
fields: function(){
console.log("trying to get fields");
const obj = ConsultationDict.get('consEdit');
cc = new ConsultationEditor(obj);
return cc.getFields();
}
But unfortunately this does not work for me.
What is your ConsultationDict?
The way you describe it, you want it to be a ReactiveDict as in the official ReactiveDict package.
https://atmospherejs.com/meteor/reactive-dict
Check this tutorial for examples:
https://themeteorchef.com/snippets/reactive-dict-reactive-vars-and-session-variables/
If you really need more fine tuning in your reactivity, you can also set a dependency tracker tracker = new Tracker.Dependency, and then refer to it wherever you change a variable with tracker.changed() and where the data needs to be notified with tracker.depend() like this:
var favoriteFood = "apples";
var favoriteFoodDep = new Tracker.Dependency;
var getFavoriteFood = function () {
favoriteFoodDep.depend();
return favoriteFood;
};
var setFavoriteFood = function (newValue) {
favoriteFood = newValue;
favoriteFoodDep.changed();
};
getFavoriteFood();
See the full Tracker doc here:
https://github.com/meteor/meteor/wiki/Tracker-Manual
I also found this gist to be useful to build reactive objects:
https://gist.github.com/richsilv/7d66269aab3552449a4c
and for a ViewModel type of behavior, check out
https://viewmodel.meteor.com/
I hope this helps.

Flex Detecting Dragged Data

I have a list that accepts drops. When an item is dropped (DragEvent.DRAG_DROP) I need to collect the data that is dropped, however I have found nothing in the event that helps me do so, event.dragInitiator.selectedItems would work but gives me an error.
Any help would be appreciated.
The data should be in event.dragSource. You'll have to check for the proper format using hasFormat() and retrieve it with dataForFormat(). Here are the docs for DragSource.
Code would be something like this (assuming this is Flex 4):
// In dragDrop handler or dragComplete
if (event.dragSource.hasFormat("itemsByIndex"))
{
var items:Vector.<Object> = event.dragSource.dataForFormat("itemsByIndex") as Vector.<Object>;
// Do stuff with items
}
You can also listen to changing dataProvider.
list.dataProvider.addEventListener(CollectionEvent.COLLECTION_CHANGE, list_dataProvider_change);
...
protected function list_dataProvider_change(e :CollectionEvent) :void
{
if (e.kind == CollectionEventKind.REMOVE)
trace('list element removed from - index', e.location);
else if (e.kind == CollectionEventKind.ADD)
trace('list element added to - index', e.location);
}

Resetting target values in a composite effect

We need to be able to handle a "playable" (play/pause/seek) effect in which the nature of the effect cannot be determined at compile time.
The problem we are running into is resetting the target(s) state after the effect has completed. If we manually drag the seek slider back to the beginning, everything works fine. However, if we set the playheadTime of the composite effect back to 0, the effected targets retain their original value until the playheadTime gets to the correct position to effect the target.
Here is a simplified (as much as I could) test case with view source enabled:
http://www.openbaseinteractive.com/_tmp/PlayableEffectTest/
The problem is demonstrated if you let it play to the end, and then hit the play button to start it over.
What is the best way to go about manually resetting the target values given that the exact nature of the effect is unknown?
Many thanks for your time!
edit
I forgot to mention we are using Flex 4.5 preview release.
Have you tried:
effect.reverse()
More info
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/effects/IEffect.html
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/effects/IEffect.html#reverse()
Well it's a little kludgy, but I was able to accomplish this by calling some internal methods on the effect to capture the start values, then assigned those values to the targets on a reset.
import mx.core.mx_internal;
use namespace mx_internal;
private var _propertyChangesArray:Array;
protected function captureStartValues(effect:Object):void
{
effect.captureStartValues();
_propertyChangesArray = effect.propertyChangesArray;
}
protected function reset(effect:Object):void
{
for each(var change:PropertyChanges in _propertyChangesArray)
{
var target:Object = change.target;
for(var p:String in change.start)
{
if(target.hasOwnProperty(p))
{
var startVal:* = change.start[p];
var endVal:* = target[p];
if(!isNaN(startVal) && startVal != endVal)
{
target[p] = startVal;
}
}
}
}
effect.playheadTime = 0;
}
I don't know if this is the best way to accomplish this, but it seems to be working so far. I am absolutely open to suggestions for a better method.
Cheers!

Is there some way to force 'updatedisplaylist' immediately rather than at later some point

In flex component life cycle, after we make some change in a components property, invalidation methods schedules a call to methods like commitProperties, updateDisplayList, etc for some later time. I need to call the updateDisplayList instantaneously. Is there some direct way to do this.
Currently, both the labels are changed simultaneously after completion of the loop. Instead I need it to work like this, to first render the updated 'myButton1' label then enter the loop and then update myButton2's label. I know, it is elastic race track issue, but isn't there some way to achieve this ?
myButton1.label = 'New Label1' ;
// Some logic to forcibly make the screen reflect it
for (var i:int = 0; i < 500 ; i ++){
//a dummy loop
}
myButton2.label = 'New Label2' ;
You can use myButton1.validateNow() but it's use is discouraged, for you may end up having the same component update itself multiple times on the same frame.
Use validateNow() . But, I would use it sparingly. using invalidateDisplayList() will force updateDisplayList() to run on the next renderer event.
A render event happens on each frame. 24 frames happen each second by default for Flex. Are you sure need to change these values quicker?
I would set the label for myButton1, then put the remaining code into a separate method and call that method using callLater:
private function foo():void {
myButton1.label = 'New Label1';
this.callLater(bar);
}
private function bar():void {
for (var i:int = 0; i < 500 ; i ++){ //a dummy loop
}
myButton2.label = 'New Label2';
}
This way myButton1 will update to show the new label before going into your loop since callLater doesn't call bar until after the event queue is cleared, giving myButton1 a chance to update.
invalidateDisplayList() or valdiateNow() will do it for you however excess of using these will end up memory leaks.

How do I force all Tree itemrenderers to refresh?

I have item renderers in an mx.controls.Tree that I need to refresh on demand.
I have code in the updateDisplayList that fires for only some of the visible nodes no matter what I do. I've tried triggering a change that they should all be listening for; I have tried clearing and resetting the dataProvider and the itemRenderer properties.
private function forceCategoryTreeRefresh(event : Event = null) : void
{
trace("forceCategoryTreeRefresh");
var prevDataProvider : Object = CategoryTree.dataProvider;
CategoryTree.dataProvider = null;
CategoryTree.validateNow();
CategoryTree.dataProvider = prevDataProvider;
var prevItemRenderer : IFactory = CategoryTree.itemRenderer;
CategoryTree.itemRenderer = null;
CategoryTree.itemRenderer = prevItemRenderer as IFactory;
_categoriesChangeDispatcher.dispatchEvent(new Event(Event.CHANGE));
}
The nodes refresh properly when I scroll them into view (e.g. the .data gets set), but I cannot force the ones that already exist to refresh or reset themselves.
Any ideas?
Try calling this function on change event:
private function refreshList(e:Event):void{
listName.invalidateSize();
listName.invalidateList();
listName.invalidateDisplayList();
listName.validateSize(true);
listName.validateNow();
}
for me work quite well
Try
treeView.dataProvider = treeView.dataProvider;
That should update Tree view.
ItemRenderers in Flex are virtualized so there will not always be one ItemRenderer for each Tree node.
However, you can invalidate the nodes to force a refresh. The answer to this question gives an example of how to do that.

Resources