In Corona SDK, many functions are asynchronous, meaning that they return control immediately to your program while they do their work in the background. When these events complete, they notify your program that they’re finished and allow you an opportunity to respond, whether it be to a touch/tap action, completion of a downloaded file, or data returned from facebook.request().

Normally you must provide a function to handle the returned value(s), and most of these functions are driven by events. In many cases, these functions take a single parameter called event which is a table that contains information about the completed event. These are referred to as callback functions.

This is easy to implement when your function calls are in the same module where you need to access the data. However, what if you want to modularize your code and you don’t have direct access to the function that handles the the call?

One solution is to code your module in such a way that you can provide your own callback function within the internal callback function. Consider this simple module:

local M = {}

function M.fetchImage( returnHandler )
   if ( returnHandler and type(returnHandler) == "function" ) then
      M.callback = returnHandler
   else
      error( "No callback function listed" )
   end

   local function networkListener( event )
      if ( event.isError ) then
         print( "Network error - download failed" )
         M.callback( event )
      elseif ( event.phase == "began" ) then
         print( "Progress Phase: began" )
      elseif ( event.phase == "ended" ) then
         print( "displaying response image file" )
         local myImage = display.newImage( event.response.filename, event.response.baseDirectory, 60, 40 )
         myImage.alpha = 0
         transition.to( myImage, { alpha = 1.0 } )
         event.target = myImage
         M.callback( event )
      end
   end

   local params = {}
   params.progress = true

   network.download(
      "http://coronalabs.com/wp-content/uploads/2013/10/Flat_Corona_250x250.png",
      "GET",
      networkListener,
      params,
      "helloCopy.png",
      system.TemporaryDirectory
   )
end

return M

This module simply fetches an image using network.download() and creates a display object with it. However, this happens in a module, and it’s likely that you’ll need to know the handle of that image in the module where you called this fetching function.

Inspecting the Function

This example function uses a mostly un-modified version of the network.download() example code which we simply wrap inside a module. The function itself takes a single parameter, returnHandler, which is the function that handles the return in your local code. In a more robust project, you’d probably accept additional parameters like the image URL to fetch, but we’ll keep it simple for this tutorial.

At the top of this function, we ensure that returnHandler exists and that it’s a function. If both are true, we store it in the module table M as the callback parameter.

Further down, in the networkListener callback function for network.download(), we call the function that’s stored as callback when we want to check the result of the download back in the module where we need that information. Also, notice that in the ended phase, the actual display object is added to the event table — this stores the handle of the image for your use.

Calling the Function

To call this function from another module, consider this simple routine:

local fetch = require( "fetchimage" )

local function postImageFetch( event )
   if not event.isError then 
      local downloadedImage = event.target
      downloadedImage.x = display.contentCenterX
      downloadedImage.y = display.contentCenterY
      print( "image is at ", downloadedImage.x, downloadedImage.y )
   end
end

fetch.fetchImage( postImageFetch )

In this manner, you can provide your own function (postImageFetch in this case) and use the event table however you want.

Conclusion

With this simple technique, you should be able to modularize your code and still have access to the data that you need.

  1. Very useful. Rob has the ability to turn complex things into simple ones, his tuto’s are really great. Thank you.

  2. Curious:

    How would one handle removing the downloaded image?

    Would one use the “downloadedImage” handle or the “myImage” handle?

    Would there be an external reference issue to worry about in this case?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>