How to use the ImageLoader component (Starling version)
The ImageLoader
class wraps starling.display.Image
inside a Feathers component to add additional features. For instance, you can easily load an image from a URL and automatically convert it to a texture that is fully managed by the ImageLoader
. The texture will be disposed when the ImageLoader
is disposed. A number of other useful properties have been added to ImageLoader
. See below for more details.
The Basics
First, let's create an ImageLoader
control, pass in a texture to display, and add it to the display list:
var loader:ImageLoader = new ImageLoader();
loader.source = texture;
this.addChild( loader );
Alternatively, you can pass a URL to the source
property to load an external image:
loader.source = "http://www.example.com/image.png";
The URL may point to any image file that may be loaded by flash.display.Loader
to create a flash.display.BitmapData
object. The loaded image will be converted to a starling.textures.Texture
.
At this time, ATF files cannot be loaded by
ImageLoader
using a URL.
Events
You can listen for Event.COMPLETE
to know when the image is fully loaded:
loader.addEventListener( Event.COMPLETE, loader_completeHandler );
The listener might look like this:
function loader_completeHandler( event:Event ):void
{
// image loaded and texture ready
}
You can also listen for errors to know if the ImageLoader
is unable to load the texture:
loader.addEventListener( Event.IO_ERROR, loader_ioErrorHandler );
The listener for Event.IO_ERROR
might look like this:
function loader_ioErrorHandler( event:Event, data:IOErrorEvent ):void
{
// loader error
}
The data
parameter in the function signature is optional, as always. It is a flash.events.IOErrorEvent
that is dispatched by the internal flash.display.Loader
used internally by the ImageLoader
.
Similarly, you may listen for Event.SECURITY_ERROR
. The data
property of the event is a flash.events.SecurityErrorEvent
dispatched by the internal Loader
.
Caching Textures
By default, the ImageLoader
will always create a new texture every time that it loads a source from a URL. In components like List
, Tree
, and GroupedList
, it's common for the same URL to be loaded multiple times by one or more ImageLoader
components. This can use extra bandwidth and affect performance.
If enough memory is available, it's possible to store the loaded textures without disposing them. An instance of the feathers.utils.textures.TextureCache
class can be shared by multiple ImageLoader
components, and if a URL has already been loaded, the texture will be taken from the cache instead of reloading the image file and creating a new texture.
To use, simply pass the same TextureCache
instance to the textureCache
property of multiple ImageLoader
components:
var cache:TextureCache = new TextureCache( 30 );
var loader1:ImageLoader = new ImageLoader();
loader1.textureCache = cache;
var loader2:ImageLoader = new ImageLoader();
loader2.textureCache = cache;
The parameter passed to the TextureCache
constructor specifies how many textures should be stored in the cache. This limit affects only textures that are not currently displayed by any ImageLoader
using the cache. The parameter defaults to int.MAX_VALUE
, but a smaller value is recommended to avoid using too much memory and crashing your application. In this case, we've chosen 30
.
For a List
, we might use a TextureCache
for icons or accessories that are loaded from URLs:
var cache:TextureCache = new TextureCache( 15 );
list.itemRendererFactory = function():IListItemRenderer
{
var itemRenderer:DefaultListItemRenderer = new DefaultListItemRenderer();
itemRenderer.iconLoaderFactory = function():ImageLoader
{
var loader:ImageLoader = new ImageLoader();
loader.textureCache = cache;
return loader;
};
return itemRenderer;
};
The dispose()
method of the TextureCache
should be called when the List
or other component using the cache is disposed. The TextureCache
does not automatically know when it should dispose its stored textures, much like how a starling.display.Image
will never dispose its own texture
property because the texture may still be needed elsewhere.
Failing to dispose a
TextureCache
will cause a pretty serious memory leak because the cache may have stored a large number of textures. Don't forget!
In the following example, let's assume that we stored a TextureCache
instance in a savedTextures
member variable in one of our screens:
override public function dispose():void
{
if( this.savedTextures )
{
this.savedTextures.dispose();
this.savedTextures = null;
}
super.dispose();
}
When the screen is disposed, we'll simply dispose the TextureCache
.
Other Properties
You can snap the position of an ImageLoader
to the nearest whole pixel using the pixelSnapping
property:
loader.pixelSnapping = true;
Pixel snapping is most useful for icons where crisp edges are especially important.
When images are loaded in a component like a List
, it's often more desirable to avoid creating new textures on the GPU while the list is scrolling. Since texture uploads are expensive, this keeps the list feeling smooth and responsive.
loader.delayTextureCreation = true;
Set the delayTextureCreation
property to true
when the container starts scrolling and set it back to false
after scrolling finishes. While this property is true
, the image may load from a URL, but the BitmapData
will be kept in memory without being converted to a texture on the GPU. Once the property is set back to false
, the texture will be created immediately.
If desired, we can set the textureQueueDuration
property to a specific number of seconds. When delayTextureCreation
is true
, the loaded image will be converted to a Texture
after a short delay instead of waiting for delayTextureCreation
to be set back to false
.
When you resize a regular starling.display.Image
, it may distort. ImageLoader
allows you control whether the image maintains its aspect ratio within the dimensions of the ImageLoader
:
loader.maintainAspectRatio = true;
When the maintainAspectRatio
property is true
, the image may be letter-boxed inside the ImageLoader
, adding transparent edges on the top and bottom or on the left and right.
You can use the isLoaded
getter to know if a texture is fully loaded (in addition to listening for Event.COMPLETE
, mentioned above):
if( loader.isLoaded )
{
// ready
}
else
{
// not loaded
}
You may set the scale factor of the loaded texture:
loader.scaleFactor = 0.5;
Using this value, the texture will be scaled to an appropriate size for Starling's current contentScaleFactor
.
Finally, just like starling.display.Image
, ImageLoader
allows you to customize the color
and textureSmoothing
properties:
loader.color = 0xff0000;
loader.textureSmoothing = TextureSmoothing.NONE;