Message text not updating

Hi all,

I have what I hope will be a fairly trivial problem. I have an update function that downloads data from a website and updates a database appropriately. I’d like some indication that there is activity taking place, so I thought I would simply put an “Updating” message on the screen and then change the text of the message to the name of the item that’s updating as I loop over them. On complete it would say “Update complete”. The “Updating” and “Update complete” parts are working, but it doesn’t change the text to the name of the current item. When I print the current item inside “updateMessage” it’s as I would expect it to be, and when I print “message.text” in the same location it also looks like what I’d expect i.e. "Updating ". The onscreen message doesn’t change though.

Any help would be appreciated.

<br>function update()<br> <br> local background = display.newRect(0,display.screenOriginY, display.contentWidth, 900)<br> background:setFillColor(0, 0, 0)<br> background.alpha = 0.7<br> <br> local message = display.newText("Updating", 0, 0, native.systemFont, 24)<br> message.x = 100 + message.width*0.5<br> message.y = display.contentCenterY<br> <br> local function updateMessage(text)<br> message.text = text<br> print("mt:"..message.text)<br> end<br> <br> local function networkListener( event )<br> <br> local function removeMessage()<br> message:removeSelf()<br> background:removeSelf()<br> end<br> <br> if ( event.isError ) then<br> message.text = "Network error!"<br> local messageTimer = timer.performWithDelay( 1500, removeMessage )<br> else<br> local data = Json.Decode(event.response)<br> for i = 1, #data.artists do<br> local present = false<br> local id = 0<br> local dataItem = data.artists[i]<br> local sql = "select id from artists where name = '"..dataItem.name.."'"<br> <br> for row in db:nrows(sql) do<br> present = true<br> id = row.id<br> end<br> <br> <br> if(present == false) then<br> sql = [[insert into artists(name,bio,day,date,venue,time) values(']]..dataItem.name..[[',']]..dataItem.bio..[[',']]..dataItem.day..[[',']]..dataItem.date..[[',]]..dataItem.venue..[[,']]..dataItem.time..[[')]]<br> updateMessage("Adding "..dataItem.name)<br> else<br> sql = [[update artists set name = ']]..dataItem.name..[[', bio=']]..dataItem.bio..[[',day=']]..dataItem.day..[[',date=']]..dataItem.date..[[',venue=]]..dataItem.venue..[[,time=']]..dataItem.time..[[' where id =]]..id..[[]]<br> updateMessage("Updating "..dataItem.name)<br> end<br> <br> print(sql)<br> db:exec( sql )<br> <br> end<br> <br> message.text = "Update complete"<br> local loadingTimer = timer.performWithDelay( 1500, removeMessage )<br> <br> end<br> end<br> <br> -- Access Google over SSL:<br> network.request( "http://www.myurl.com/test.txt", "GET", networkListener )<br>end<br> [import]uid: 69057 topic_id: 11299 reply_id: 311299[/import]

That should read ’ i.e. “Updating current item”’. [import]uid: 69057 topic_id: 11299 reply_id: 41032[/import]

I would also like an explanation for this as it seems whenever there is a piece of work that takes a long time and runs outside of the “enterFrame” event handler the display is effectively prevented from update.

Below is a simple piece of code that demonstrates the issue/question. It should run by pasting it straight into a main.lua file with the only dependency being the undescore.lua library which is readily available or else just replace the “each” call with a regular lua loop.

The intent of this code is to display a string of five dots, starting with one dot and displaying one more as each work item is started. In other words very similar contact59’s example but without any server or network dependencies.

The actual result however is that the user sees nothing happen while the work gets done and then “Done!” appears.

[lua]_ = require(“underscore”)
local workItems = {1,2,3,4,5,6,7,8,9,10}
local loadingText = display.newText("…", 0, display.contentHeight, system.nativeFont, 80)
loadingText:setReferencePoint(display.CenterReferencePoint)
loadingText.x = display.contentWidth / 2
loadingText.y = display.contentHeight / 2

_(workItems):each(function(workItem)
– update loading indicator
if loadingText.text:len() < 5 then
loadingText.text = loadingText.text…"."
else
loadingText.text = “.”
end

– Do some work that takes time i.e. simulate loading stuff
for i = 1, 10000000, 1 do
local dummy = i * i / 1.34567
end
end)
loadingText.text = “Done!”
[lua]I will try some other methods and post back. [import]uid: 60648 topic_id: 11299 reply_id: 77913[/import]

So I tried offloading the display update into an enterFrame handler and making it time based rather than work completed based:
[lua]_ = require(“underscore”)
local workItems = {1,2,3,4,5,6,7,8,9,10 }
local text = “…”
local loadingText = display.newText("…", 0, 0, system.nativeFont, 80)
loadingText:setReferencePoint(display.CenterReferencePoint)
loadingText.x = display.contentWidth / 2
loadingText.y = display.contentHeight / 2
local startX = loadingText.contentBounds.xMin

local lastUpdateTime = 0
local updateProgress = function()
local now = os.time()
local elapsedTime = now - lastUpdateTime
if elapsedTime > 0 then
if text:len() < 5 then
text = text…"."
else
text = “.”
end
loadingText:removeSelf()
loadingText = display.newText(text, startX, 0, system.nativeFont, 80)
loadingText.y = display.contentHeight / 2
lastUpdateTime = now
end
end

Runtime:addEventListener( “enterFrame”, updateProgress )

_(workItems):each(function(workItem)

print(" Performing work! ")
– Do some work that takes time i.e. simulate loading stuff
for i = 1, 10000000, 1 do
local dummy = i * i / 1.34567
end
end)
Runtime:removeEventListener(“enterFrame”, updateProgress)
loadingText.text = “Done!”
loadingText.x = display.contentWidth / 2
loadingText.y = display.contentHeight / 2[/lua]

Same result, so I tried putting the work in a timer:
[lua]_ = require(“underscore”)
local workItems = {1,2,3,4,5,6,7,8,9,10 }
local text = “…”
local loadingText = display.newText("…", 0, 0, system.nativeFont, 80)
loadingText:setReferencePoint(display.CenterReferencePoint)
loadingText.x = display.contentWidth / 2
loadingText.y = display.contentHeight / 2
local startX = loadingText.contentBounds.xMin

local lastUpdateTime = 0
local updateProgress = function()
local now = os.time()
local elapsedTime = now - lastUpdateTime
if elapsedTime > 0 then
if text:len() < 5 then
text = text…"."
else
text = “.”
end
loadingText:removeSelf()
loadingText = display.newText(text, startX, 0, system.nativeFont, 80)
loadingText.y = display.contentHeight / 2
lastUpdateTime = now
end
end

Runtime:addEventListener( “enterFrame”, updateProgress )

timer.performWithDelay(2000, function()
_(workItems):each(function(workItem)

print(" Performing work! ")
– Do some work that takes time i.e. simulate loading stuff
for i = 1, 10000000, 1 do
local dummy = i * i / 1.34567
end
end)
Runtime:removeEventListener(“enterFrame”, updateProgress)
loadingText.text = “Done!”
loadingText.x = display.contentWidth / 2
loadingText.y = display.contentHeight / 2
end)[/lua]

The display updates during the delay of 2 seconds before the timer initiates the work but does not while the work is being performed. i.e. the effect from a user perspective is that the loading indicator freezes at 3 dots until the work is performed and then “Done!” appears.

Clearly there is something fundamental about the way Corona works that I (we) do not understand. Can anyone please explain?

Currently the only solution I can think of is to break any long running work up and have it execute inside an enterFrame handler, but this seems annoying at best if for example you wanted to display a more sophisticated animation whilst performing some work you would need to break the work into small enough chunks to run in less than 1/30th of a second…

[import]uid: 60648 topic_id: 11299 reply_id: 77926[/import]