Table View And Load Remote Image

Hi there,

If I am using display.loadRemoteImage to load a image thumb for every row in my tableView, does it mean that every time the row is rendered the image will be re-downloaded? Is there anyway to cache the image? Or does corona detect that the image already exists and then just load it from memory?

Thanks!

I suspect that we are downloading them each time, but if you use the “File->Show Project Sandbox” and look in either the tmp folder or the Caches folder and see if the files are there, do a reload and see if the date/time stamps update.  If they don’t update, then we are using the cached version, if they do update, we are re-downloading them.

You can also use your own cache method if you want.  You can look to see if the filename exists and if it does load it, if it doesn’t then download it.  Then if it’s something like Facebook pics, where people change them from time to time, you might want to look at the timestamp (using LFS) and if it’s older than a few days, reload it.

Thanks Rob! Could you just give me a simple example of how to go about the if statement to check if the image exists? 

Thanks Rob,

I tried this piece of code and it does the job! Thanks again!

function fileExists(myFile, directoryName)

        local filePath = system.pathForFile(myFile, directoryName)
        local results = false
        if filePath == nil then
                return false
        else
                local file = io.open(filePath, “r”)
                --If the file exists, return true
                if file then
                        io.close(file)
                    results = true
                end
                return results
        end
end

–check a file
if fileExists(“t[row.index].imageName”, system.CachesDirectory) then
    – load image
else
    --download  image
end

Hi mastersdktester,

I had this issue while I tried to streamline my app. Here is how I implemented a way to check whether the file exist in the tmp-folder (note that it gets deleted by Android/iOS)

 function extractImageName( url ) -- This will loop and find the last occurence of the character local function searchChar(url, index, char) local startOfFilename = string.find( url, char, index) -- print(startOfFilename) if startOfFilename ~= nil then return searchChar(url, startOfFilename + 1, char) else return index end end local startOfFilename = searchChar( url, 1, "/" ) -- print(startOfFilename) local returnData if startOfFilename == nil then returnData = nil else returnData = string.sub(url, startOfFilename ) end return returnData end function doesFileExist( fname, path ) local results = false local filePath = system.pathForFile( fname, path ) if filePath then filePath = io.open( filePath, "r" ) end if filePath then -- Clean up our file handles filePath:close() results = true else print( "File does not exist -\> " .. fname ) end return results end 

Here is how to use it :

local url = "http://eofdreams.com/data\_images/dreams/image/image-07.jpg" local imgFilename = extractImageName( url ) if imgFilename == nil then -- No filename found! Edit this depending on how to want to handle it. return end local function networkListener( event ) if ( event.isError ) then print ( "ERROR RESPONSE: ", event.response.filename ) else print ( "RESPONSE: ", event.response.filename ) end end if doesFileExist( imgFilename, system.TemporaryDirectory) then print("Picture file exist! " .. imgFilename) -- Use it! local imgImage = display.newImageRect(imgFilename , system.TemporaryDirectory, 100, 100) else local tmpID = network.download( url, "GET", networkListener, imgFilename, system.TemporaryDirectory ) -- save the download id, so you can cancel it if needed (e.g. user leaves the page) table.insert(g\_downloadID, tmpID) end

I suspect that we are downloading them each time, but if you use the “File->Show Project Sandbox” and look in either the tmp folder or the Caches folder and see if the files are there, do a reload and see if the date/time stamps update.  If they don’t update, then we are using the cached version, if they do update, we are re-downloading them.

You can also use your own cache method if you want.  You can look to see if the filename exists and if it does load it, if it doesn’t then download it.  Then if it’s something like Facebook pics, where people change them from time to time, you might want to look at the timestamp (using LFS) and if it’s older than a few days, reload it.

Thanks Rob! Could you just give me a simple example of how to go about the if statement to check if the image exists? 

Thanks Rob,

I tried this piece of code and it does the job! Thanks again!

function fileExists(myFile, directoryName)

        local filePath = system.pathForFile(myFile, directoryName)
        local results = false
        if filePath == nil then
                return false
        else
                local file = io.open(filePath, “r”)
                --If the file exists, return true
                if file then
                        io.close(file)
                    results = true
                end
                return results
        end
end

–check a file
if fileExists(“t[row.index].imageName”, system.CachesDirectory) then
    – load image
else
    --download  image
end

Hi mastersdktester,

I had this issue while I tried to streamline my app. Here is how I implemented a way to check whether the file exist in the tmp-folder (note that it gets deleted by Android/iOS)

 function extractImageName( url ) -- This will loop and find the last occurence of the character local function searchChar(url, index, char) local startOfFilename = string.find( url, char, index) -- print(startOfFilename) if startOfFilename ~= nil then return searchChar(url, startOfFilename + 1, char) else return index end end local startOfFilename = searchChar( url, 1, "/" ) -- print(startOfFilename) local returnData if startOfFilename == nil then returnData = nil else returnData = string.sub(url, startOfFilename ) end return returnData end function doesFileExist( fname, path ) local results = false local filePath = system.pathForFile( fname, path ) if filePath then filePath = io.open( filePath, "r" ) end if filePath then -- Clean up our file handles filePath:close() results = true else print( "File does not exist -\> " .. fname ) end return results end 

Here is how to use it :

local url = "http://eofdreams.com/data\_images/dreams/image/image-07.jpg" local imgFilename = extractImageName( url ) if imgFilename == nil then -- No filename found! Edit this depending on how to want to handle it. return end local function networkListener( event ) if ( event.isError ) then print ( "ERROR RESPONSE: ", event.response.filename ) else print ( "RESPONSE: ", event.response.filename ) end end if doesFileExist( imgFilename, system.TemporaryDirectory) then print("Picture file exist! " .. imgFilename) -- Use it! local imgImage = display.newImageRect(imgFilename , system.TemporaryDirectory, 100, 100) else local tmpID = network.download( url, "GET", networkListener, imgFilename, system.TemporaryDirectory ) -- save the download id, so you can cancel it if needed (e.g. user leaves the page) table.insert(g\_downloadID, tmpID) end

Is there an easy way to download an image each time with a networkListener? As I understand this here an image is downloaded and used from the local version when the download is finished. How can I “overwrite” the local version with a new downloaded image of the same name?

There is an old “cache busting” technique that’s worked for years.  Simply append a query string on the end of your url with a randomish number that will make the URL unique.

For instance if your URL is:

http://www.mysite.com/myimage.jpg

you could do:

http://www.mysite.com/myimage.jpg?cb=12304

The number at the end just has to be different than any previous call.  Some people might keep a counter and increment it.  Some people would use the os.time() call to get the time in seconds since Jan 1, 1970, which would always be a unique value, or use something from math.random().

The ? starts the query string on a URL, the cb is made up and something the URL would likely not use, and kinda means “Cache Bust”.

Rob

Thx Rob… I tried the following:
 

var.request2=display.loadRemoteImage(                     (serverlinkpath.."newgameserverimg.png?cb="..actualtime),                     "GET",                     ImageNetworkListener,                     params,                     "newgame.png",                     system.TemporaryDirectory,367,179                 )

But once the file “newgame.png” was created it will always be used from the Temporary Directory. When I update the server image the file shown on device is always the old one, even with a new ‘actualtime’ value for the link.

Did I miss something here or do I use it the wrong way?

Thank you for your fast help!

  • Daniela

UPDATE:

PS: Oh… is there a difference between display.loadRemoteImage and network.download in this case? I just changed it to network.download and now it seems to work!?

They both should basically be doing the same thing with of course the exception that display.loadRemoteImage() will actually load the image.  It’s just a convenience method around network.download anyway.  So if network.download is working for you I would keep it that way.

Rob

Is there an easy way to download an image each time with a networkListener? As I understand this here an image is downloaded and used from the local version when the download is finished. How can I “overwrite” the local version with a new downloaded image of the same name?

There is an old “cache busting” technique that’s worked for years.  Simply append a query string on the end of your url with a randomish number that will make the URL unique.

For instance if your URL is:

http://www.mysite.com/myimage.jpg

you could do:

http://www.mysite.com/myimage.jpg?cb=12304

The number at the end just has to be different than any previous call.  Some people might keep a counter and increment it.  Some people would use the os.time() call to get the time in seconds since Jan 1, 1970, which would always be a unique value, or use something from math.random().

The ? starts the query string on a URL, the cb is made up and something the URL would likely not use, and kinda means “Cache Bust”.

Rob

Thx Rob… I tried the following:
 

var.request2=display.loadRemoteImage(                     (serverlinkpath.."newgameserverimg.png?cb="..actualtime),                     "GET",                     ImageNetworkListener,                     params,                     "newgame.png",                     system.TemporaryDirectory,367,179                 )

But once the file “newgame.png” was created it will always be used from the Temporary Directory. When I update the server image the file shown on device is always the old one, even with a new ‘actualtime’ value for the link.

Did I miss something here or do I use it the wrong way?

Thank you for your fast help!

  • Daniela

UPDATE:

PS: Oh… is there a difference between display.loadRemoteImage and network.download in this case? I just changed it to network.download and now it seems to work!?

They both should basically be doing the same thing with of course the exception that display.loadRemoteImage() will actually load the image.  It’s just a convenience method around network.download anyway.  So if network.download is working for you I would keep it that way.

Rob