Developing Android Applications with Adobe AIR [113]
SQLite operation can be done in synchronous or asynchronous mode. Only one mode can be used at a time:
SQLConnection.openAsync();
SQLConnection.open();
Operations on the filesystem can also be asynchronous. Use such operations for fairly large files:
fileStream.openAsync(file, FileMode.READ);
fileStream.open(file, FileMode.READ);
If your code performs long operations, you can restructure it to execute in chunks instead of all at once.
Rendering related to sensors should be done on EnterFrame, not when the sensor updates, which can be more frequent than the refresh rate and can be irregular. If you use EnterFrame, create a single listener to manage all your objects.
Never use the updateAfterEvent function. It forces rendering for faster animation. On mobile devices, it will reduce your frame rate. If you need extremely high-speed animation, AIR is not the right tool for the job.
Setting the stage quality to low, or toggling settings, is a good option for faster rendering:
stage.quality = StageQuality.LOW;
stage.quality = StageQuality.HIGH;
Memory
Let’s say it one more time: the memory on mobile devices is limited. If you exceed it, Android will terminate your application.
Creating Objects
Choose the appropriate object. For instance, use a Sprite instead of a MovieClip if you don’t need multiple frames. Use a Vector, which is more efficient than an Array, to store objects. Call the getSize() function to determine the memory footprint for a particular data type.
Allocating new blocks of memory is costly. Create your objects at an idle time, ideally when your application first initializes, and reuse them throughout your application.
Object pooling creates a pool to store objects and re-use them over time. In this example, we pop an object, or create one if none exists, and then push it back when done until the next use:
import flash.display.Sprite;
var pool:Vector. // get a new Sprite var sprite:Sprite = popSprite(); sprite.init(); // set properties as needed addChild(sprite); function popSprite():Sprite { var sprite:Sprite; if (pool.length > 0) { sprite = pool.pop(); } else { sprite = new Sprite(); } return sprite; } When the object is no longer needed, return it: removeChild(sprite); pushSprite(sprite); function pushSprite(sprite:Sprite):void { pool.push(sprite); } This approach is organic. The application creates objects as needed until it reaches a sufficient quantity to recycle them. Another method is to create all the objects initially, up to a maximum amount. Removing Objects Only primitive types, such as String, Number, and Boolean, are used directly. All other types are used using a reference, which must be removed to clear them from memory. This includes removing a child from a displayList, splicing an Array array or a Vector, stopping and deleting a Timer, removing an EventListener, or nulling a reference from another object. Once this is all done, set the object to null to help the garbage collector work more quickly. Use the disposeXML method for an XML object. It traverses the tree and sets all pointers between parents and children to null to make the object available for immediate garbage collection: import flash.system.System; function onXMLLoaded(event:Event):void { var xml:XML = event.target.data; // sudo code to parse and store data var dataStorage = parseXML(XML); System.disposeXML(xml); xml = null; } Use the dispose method for a BitmapData object: var bitmapData:BitmapData = new BitmapData(480, 800); bitmapData.dispose(); bitmapData = null; One of the principal reasons for memory leaks is lingering event listeners. A common recommendation today is to set weak event listeners as shown in the code below. Weak references are not counted by
Memory is dynamic. As objects are deleted, memory is released via a process called garbage collection.