23 August 2012

Reading/Writing bytes or binary data in Flex

Hi,

Recently I came up with a problem where I was supposed to read a PDF file, send bytes to server (using webservice) and then later in the application download those bytes and generate the PDF again.

Though it is a simple solution but I thought it would be good to share. Here is the code for your reference:-


<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
  xmlns:s="library://ns.adobe.com/flex/spark" 
  xmlns:mx="library://ns.adobe.com/flex/mx">

 <fx:Declarations>
  <s:HTTPService id="httpSVC" url="URL TO WEBSERVICE" method="POST" resultFormat="text" showBusyCursor="true"
  result="httpSVC_resultHandler(event)" 
  fault="httpSVC_faultHandler(event)"/>
 </fx:Declarations>
 <fx:Script>
  <![CDATA[
   import mx.rpc.events.FaultEvent;
   import mx.rpc.events.ResultEvent;
   import mx.utils.Base64Decoder;
   import mx.utils.Base64Encoder;
   
   protected function httpSVC_resultHandler(event:ResultEvent):void
   {
    var stream:FileStream;
    var newFile:File
    var decoder:Base64Decoder;
    var bytes:ByteArray
    var xml:XML = new XML(httpSVC.lastResult);
    var str:String = xml.toString();    
    
    decoder = new Base64Decoder();        
    decoder.decode(str);
    
    bytes = decoder.toByteArray();   
    file = File.desktopDirectory.resolvePath("newPDF.pdf");
        
    stream = new FileStream();
    stream.open(newFile, FileMode.WRITE);
    stream.writeBytes(bytes, 0, bytes.length);
    stream.close();
           
   } 
   
   protected function httpSVC_faultHandler(event:FaultEvent):void
   {
    trace("Fault = "+event.fault)
   }

   
   public function uploadFile():void
   {
    var encoder:Base64Encoder
    var bytes:ByteArray = new ByteArray();    
    var urlVars:URLVariables = new URLVariables();    
    var stream:FileStream = new FileStream();
    
    var file:File = File.applicationDirectory.resolvePath("source.pdf");
    
    stream.open(file, FileMode.READ);    
    stream.readBytes(bytes,0,stream.bytesAvailable);    
    stream.close();
    
    encoder = new Base64Encoder();
    encoder.encodeBytes(bytes, 0, bytes.length);
    
    
    /*Process to sending Data to the server*/
    urlVars.fileBytes = encoder.toString();
    httpSVC.send(urlVars);     
   }
  ]]>
 </fx:Script>
 <s:Button label="upload" click="uploadFile()"/>
</s:WindowedApplication>

28 July 2012

Actionscript Code Optimization Part I


Hi all,

We all talk about fine tuning the code, adjust it, find out the reason for memory linkage etc. but most of the times we end up with different techniques used across projects to make it better. I thought it would be a good idea if we know in and out of Flash player and the way it handles code. For e.g. get to know about why we should use int in place of Number and what kind of memory is taken by both these primitives data types.

I have split this in to different posts so it won't be too much for us to grasp the information at one point of time. So we will take baby steps in order to learn these techniques and gradually reach to our goal.

Here we go:-

1. Conserving memory


1.1 Display Objects


 Choose an appropriate display object

ActionScript 3.0 includes a large set of display objects. One of the most simple optimization tips to limit memory usage is to use the appropriate type of display object. For simple shapes that are not interactive, use Shape objects. For interactive objects that don’t need a timeline, use Sprite objects. For animation that uses a timeline, use MovieClip objects. Always choose the most efficient type of object for your application.
The following code shows memory usage for different display objects:

trace(getSize(new Shape()));
// output: 236

trace(getSize(new Sprite()));
// output: 412

trace(getSize(new MovieClip()));
// output: 440

1.2  Primitive types

All primitive types except String use 4 – 8 bytes in memory. There is no way to optimize memory by using a specific type for a primitive:

// Primitive types
var a:Number;
trace(getSize(a));
// output: 8

var b:int;
trace(getSize(b));
// output: 4

var c:uint;
trace(getSize(c));
// output: 4

var d:Boolean;
trace(getSize(d));
// output: 4

var e:String;
trace(getSize(e));
// output: 4

A Number, which represents a 64-bit value, is allocated 8 bytes by the ActionScript Virtual Machine (AVM), if it is not assigned a value. All other primitive types are stored in 4 bytes.
// Primitive types
var a:Number = 8;
trace(getSize(a));
// output: 4

a = Number.MAX_VALUE;
trace(getSize(a));
// output: 8

The behavior differs for the String type. The amount of storage allocated is based on the length of the String:
var name:String;
trace(getSize(name));
// output: 4

name = "";
trace(getSize(name));
// output: 24


1.3 Reusing objects


 Reuse objects, when possible, instead of recreating them.

Another simple way to optimize memory is to reuse objects and avoid recreating them whenever possible. For example, in a loop, do not use the following code:

const MAX_NUM:int = 18;
const COLOR:uint = 0xCCCCCC;
var area:Rectangle;
for (var:int = 0; i < MAX_NUM; i++)
{
// Do not use the following code
area = new Rectangle(i,0,1,10);
myBitmapData.fillRect(area,COLOR);
}

Recreating the Rectangle object in each loop iteration uses more memory and is slower because a new object is created in each iteration. Use the following approach:

const MAX_NUM:int = 18;
const COLOR:uint = 0xCCCCCC;
// Create the rectangle outside the loop
var area:Rectangle = new Rectangle(0,0,1,10);

for (var:int = 0; i < MAX_NUM; i++)
{
area.x = i;
myBitmapData.fillRect(area,COLOR);
}


1.4 Object pooling


 Use object pooling, when possible.

Another important optimization is called object pooling, which involves reusing objects over time. You create a defined number of objects during the initialization of your application and store them inside a pool, such as an Array or Vector object. Once you are done with an object, you deactivate it so that it does not consume CPU resources, and you remove all mutual references. However, you do not set the references to null, which would make it eligible for garbage collection. You just put the object back into the pool, and retrieve it when you need a new object.

Reusing objects reduces the need to instantiate objects, which can be expensive. It also reduces the chances of the garbage collector running, which can slow down your application. The following code illustrates the object pooling technique:

package
{
import flash.display.Sprite;
public final class SpritePool
{
private static var MAX_VALUE:uint;
private static var GROWTH_VALUE:uint;
private static var counter:uint;
private static var pool:Vector.;
private static var currentSprite:Sprite;
public static function initialize( maxPoolSize:uint, growthValue:uint ):void
{
MAX_VALUE = maxPoolSize;
GROWTH_VALUE = growthValue;
counter = maxPoolSize;
var i:uint = maxPoolSize;
pool = new Vector.(MAX_VALUE);
while( --i > -1 )
pool[i] = new Sprite();
}

public static function getSprite():Sprite
{
if ( counter > 0 )
return currentSprite = pool[--counter];
var i:uint = GROWTH_VALUE;
while( --i > -1 )
pool.unshift ( new Sprite() );

counter = GROWTH_VALUE;
return getSprite();
}

public static function disposeSprite(disposedSprite:Sprite):void
{
pool[counter++] = disposedSprite;
}
}
}

The SpritePool class creates a pool of new objects at the initialization of the application. The getSprite() method returns instances of these objects, and the disposeSprite() method releases them. The code allows the pool to grow when it has been consumed completely. It’s also possible to create a fixed-size pool where new objects would not be allocated when the pool is exhausted. Try to avoid creating new objects in loops, if possible.

const MAX_SPRITES:uint = 100;
const GROWTH_VALUE:uint = MAX_SPRITES >> 1;
const MAX_NUM:uint = 10;
SpritePool.initialize ( MAX_SPRITES, GROWTH_VALUE );
var currentSprite:Sprite;
var container:Sprite = SpritePool.getSprite();
addChild ( container );
for ( var i:int = 0; i< MAX_NUM; i++ )
{
for ( var j:int = 0; j< MAX_NUM; j++ )
{
currentSprite = SpritePool.getSprite();
currentSprite.graphics.beginFill ( 0x990000 );
currentSprite.graphics.drawCircle ( 10, 10, 10 );
currentSprite.x = j * (currentSprite.width + 5);
currentSprite.y = i * (currentSprite.width + 5);
container.addChild ( currentSprite );
}
}

The following code removes all the display objects from the display list when the mouse is clicked, and reuses them later for another task:

stage.addEventListener ( MouseEvent.CLICK, removeDots );
function removeDots ( e:MouseEvent ):void
{
while (container.numChildren > 0 )
SpritePool.disposeSprite (container.removeChildAt(0) as Sprite );
}


There are many other ways you can optimize the code to make your application perform better. We would be discussing more on this in next post in this series.

Till then Happy Coding. 


Ankur