I have finished my newbie asynchronous image loader, and the code in its entirety is shown below for anyone who’s interested. This is an amateur attempt, so I’m not sure if this code is fully optimised etc.
--
-- Asynchronous image loader into a widget.tableView with 'image loading' placeholder and detection of images already cached
--
local http = require("socket.http")
local json = require("json")
local ui = require("ui")
local widget = require("widget")
local isCategory = false
local rowHeight = 80
local rowColor = { 255, 255, 255, 255 }
local lineColor = {0,0,0,255}
-- Get the products from TDS (JSON formatted):
response\_body\_JSon = http.request("http://www.mysite.com/somescript.asp")
jSon\_result = json.decode(response\_body\_JSon)
local listOptions = {
top = display.statusBarHeight,
height = 450,
maskFile = "mask320x410.png"
}
local list = widget.newTableView( listOptions )
-- onEvent listener for the tableView
local function onRowTouch( event )
-- whatever, swipes etc
end
local function file\_exists( name )
local path = system.pathForFile( name, system.DocumentsDirectory )
local f=io.open(path,"r")
if f~=nil then
io.close(f)
return true
else
return false
end
end
-- onRender listener for the tableView
local function onRowRender( event )
local row = event.target
local rowGroup = event.view
-- The next line is critical, without it the images still arriving will not render immediately
row.reRender = true
if file\_exists( jSon\_result.data.image1[event.index] ) then
local img = display.newImage( jSon\_result.data.image1[event.index], system.DocumentsDirectory, 0, 0 )
img:setReferencePoint( display.CenterLeftReferencePoint )
img.y = row.height \* 0.5
img.x = 15
img:scale(0.4, 0.4)
rowGroup:insert( img )
else
-- The image has not yet downloaded, or was not found so show a placeholder for now:
local img = display.newImage( "loader.gif", system.ResourcesDirectory, 0, 0 )
img:setReferencePoint( display.CenterLeftReferencePoint )
img.y = row.height \* 0.5
img.x = 15
img:scale(0.4, 0.4)
rowGroup:insert( img )
print("Downloading image: " .. jSon\_result.data.image1[event.index] )
end
local text = display.newRetinaText( jSon\_result.data.name[event.index], 200, 20, "Georgia", 9 )
text:setReferencePoint( display.CenterLeftReferencePoint )
text.y = row.height \* 0.5
text.x = 80
text:setTextColor( 0 )
rowGroup:insert( text )
end
local function img\_networkListener( event )
if (event.isError) then
print("Error loading image: " .. event.response)
else
-- Image has downloaded, so show it:
local rowHeight, rowColor, lineColor, isCategory
list:insertRow {
onEvent=onRowTouch,
onRender=onRowRender,
height=rowHeight,
isCategory=isCategory,
rowColor=rowColor,
lineColor=lineColor
}
end
end
-- Download the images, and load table data
for i=1,jSon\_result.recordcount do
-- Get the images:
if file\_exists( jSon\_result.data.image1[i] ) then
-- This file is already cached, so just display the row:
print(jSon\_result.data.image1[i] .. " already downloaded")
local rowHeight, rowColor, lineColor, isCategory
list:insertRow {
onEvent=onRowTouch,
onRender=onRowRender,
height=rowHeight,
isCategory=isCategory,
rowColor=rowColor,
lineColor=lineColor
}
else
network.download(
"http://www.mysite.com/images/" .. jSon\_result.data.image1[i],
"GET",
img\_networkListener,
jSon\_result.data.image1[i],
system.DocumentsDirectory
)
end
end
local function refreshRows()
for x=1,jSon\_result.recordcount do
list.content.rows[x].reRender = true
local pos = list:getScrollPosition()+400
end
end
This code will detect if an image is already cached (in the system.DocumentsDirectory folder) and will not download the image again - this helps speed things up. A placeholder in the system.ResourcesDirectory (loader.gif) loads if an image is not available; this is later replaced by the image itself. If you’re quick enough (or have a slow server) you can see the transition from loading to loaded.
The row.reRender = true is the one bit of crucial code that allows the transition from loading to loaded to occur; without it the images that arrive later do not update (however they will if you click or scroll).
This code loads a JSON data source, which looks like this (one row of data shown here):
{"recordcount":1,"columnlist":"firstname,image1,lastname,name,orderdt,orderstatus\_id,order\_id,unitprice","data":{"firstname":["John"],"image1":["image1.jpg"],"lastname":["Smith"],"name":["Whatever product name"],"orderdt":["Jan 12 2012 7:44PM"],"orderstatus\_id":[1],"order\_id":[123],"unitprice":["$100.00"]}}
[import]uid: 116752 topic_id: 20267 reply_id: 79503[/import]