Sunday, February 14, 2010

Compiling Release Build in Flex - non-alerted memory error:

I use Eclipse with FB3 plug-in for all my development, and often can become the case with opportunistic applications, Eclipse will grab more and more memory.  If I'm working on 2-3 apps at once, compiling and changing objects, I quickly lose up to 500MB to Eclipse.  Garbage collection and heap status size are determined by the .ini file.  When working on projects that have to embed a couple of fonts, I've had to increase the size, so that the compiler doesn't give me an out of memory error and ask me to close my workbench.

Well, to keep Eclipse from becoming a memory hog, I changed the runtime and max perm size to 128 respectively.  This normally keeps Eclipse happy, running pretty quickly, and about as close to 300MB at runtime as I can keep it.  Well, recently while building out a project, I tried to export my final build, and the application kept crashing or bombing out.  The problem was that it wasn't telling me what was going on.  It just kept stopping, and not giving me a reason why.  I knew something was wrong because the release-bin folder remained empty.

Switching over to Eclipse's plug-in development, I checked the error logs (very, very important resource when Flex and Eclipse fail without giving you warning…).  The error:
java.lang.reflect.InvocationTargetException
.
.
.
Caused by: java.lang.OutOfMemoryError: Java heap space
Root exception:
java.lang.OutOfMemoryError: Java heap space

Aha! Eureka - my answer lay in the fact that I had changed my workbench max and permanent size to something smaller than it could use, but it wouldn't tell me that.  Why Eclipse, is there now message?  Well, glad I know how to find the error log in Eclipse.

Hope this helps anyone else who's Release Build fails, and no answer/reason is given…

Thursday, February 4, 2010

Dynamically Showing Embedded Images in Flex

Dynamically Showing Embedded Images

Several resources will show how easy it is to embed an Image in Flex. You can embed inline, via meta tag, and another way (which I forgot right now). Regardless of any of these ways, they assume you always know when you are going to be using your embedded image, and don't have much flexibility if you want to dynamically change the image for a component based on something as arbitrary as mouseOver.

If you look at the profuse examples when googling, you come across many that show you how to embed inline:
<
<mx:Image id="img" source="{@Embed(source=assets/img.jpg)}" />

Or you can embed an image via metatag inside your class, and then call it explicitly in your component:

<mx:Metadata>
[Embed(source="assets/icons/myImg.png")]
public static const myImg:Class;
</mx:Metadata>

<mx:Image id="img" source="{myImg}" />

Or you can embed the object in another class, foo, and then reference it in your Image:

import location.for.assetClass.foo;
...
<mx:Image id="img" source="{foo.myImg}" />

More often than not, I like to go the third route, mainly because I want to be able to access the images from another class, or from multiple components. Now knowing how to embed images is great, but my quandary was, "What do I do if I have 30 or 100 small icons/images that I want to embed, and the component that is using the image doesn't know the embedded image to use until runtime, i.e. itemRenderer, or dynamically generated object using static icons (recycled buttons…)?"

For this example, I am using a simple list, with a custom itemRenderer. The list's dataprovider has an id and some other information for each record. In my customItemRenderer, I can get the data.id and use that to determine the picture I wanted to use. The only problem was, I have know idea how to call foo.myImg dynamically. I tried getClassByName(data.id), but it refused to cast my object to a class or would return null.

I really thought that because I had embedded my image, then cast it as a class, I'd be able to call it by name. Bummer!

Next I setup an array and a method inside of class foo. The array, called myAssets, is an array of all the classes inside of foo. The function was called from the itemRenderer, in init() to get the class for the image to assign it, as a ByteAsset, to the source for the image. Inside of foo, I have the following:

public function getClass(str:String):Class{
var s:String = "[class IconAssets_" + str + "]";
for (var i:int = 0; i < myAssets.length; i++){
var t:String = myAssets[i].toString();
trace(t);
if(s == t){
return myAssets[i];
}
}
return null;
}

I would pass in the data.id to the getClass(), and the return would be the class I needed. This actually worked, but seemed quite cumbersome, especially because now I was not only responsible for creating the embedded image, but also adding and maintaining an array for all objects. This seemed a bit extraneous, so I finally hit on a solution that let's me do this quickly and easily.

The most annoying part of all of this is either not knowing the correct syntax (because I'm a music major and am learning coding on my own), wording to search the world of Flex development blogs, or something else involving the continual error between seat and keyboard…

Anyways, the ultimate solution was actually quite easy.

Keeping the foo class with all my embedded images is fine, and in my itemRenderer, for the image, I just need to put the following for the source:

<mx:Image id="img" source="{foo[data.id]}" />

That's it! Probably too much time spent trying to figure this out, but in the end, the class is acting like an object, and I can get any of my "properties" out of the class pretty easily now. I struggled w/ this concept on an earlier project, but now that I have the quick fix to dynamically change the source of an image with an embedded image without having to hard code any values in the component is much, much better. Ok, so lesson learned, the answer wasn't that hard, but I needed to futz with the other possibilities before I could finally get it right. Now that I got it right, I promise I shouldn't get it wrong again*.

*I might, but that's all part of my slow learning.