Sample code that says: Warning - This method is not called on the main UI thread

Hi, I’m real excited about Corona Native (great work guys!) and have been studying the code in this folder carefully:

\corona native\SimpleLuaExtension\android\app\src\main\java\com\mycompany\simpleluaextension\

I see this mentioned often in the comments:

Warning! This method is not called on the main UI thread.

What does that mean for the developer? Does that mean just don’t make changes to the displayed UI otherwise the app might crash? But it should be fine to call other Android functions that just do calculations or deal with audio for example? 

Thanks

Dear John, 

I have seen the same comments at the code. I really don’t know about what it really mean. I figure it is to let developer known that this functions or methods are called directly from Lua, not from inner Android. But I’m not sure.

I’m testing too with the code.

Have you already discovered how the ‘myTest’ expression can call to the functions at native java? There is any require at the lua code.

I have replaced the myTest for other words and an error occurs.

myTests.printTableValuesXY({ x = 1, y = 2, z = 3 }) myTests.printTableValuesXY({ x = "I'm all alone." }) function onCall() print("callLuaFunction() has succeeded") end myTests.callLuaFunction(onCall)

There is not ‘require’ at the beginning of the lua code.

I can’t figure how native code can link the myTest expression with the functions.

Have you any idea?

Regards from Spain,

Hey!

So, Android have a tendency to run multiple threads. Those are parallel units of execution, and you cannot, say Invoke Lua from other thread than one which runs Lua, because then you can (and will) get situation when you interrupt Lua in undefined state to execute your code and it will break both currently executing code and your code.

Same goes for Android UI - all interactions with Android UI should be performed when no other Android UI interactions are performed, i.e., on UI thread.

So, for that reason there are execution queues. Those are pieces of code, you can send to be executed on separate thread. With UI and Lua - specific threads.

There are examples provided in Native for both cases. My favourite example is in Project Template. First - 

activity.runOnUiThread(new Runnable() {     @Override     public void run() { .........     } });

This allows to start some UI from Lua thread. It would run … on UI thread, allowing to create new widgets etc.

Another example is 

        CoronaEnvironment.getCoronaActivity().getRuntimeTaskDispatcher().send( new CoronaRuntimeTask() {             @Override             public void executeUsing(CoronaRuntime runtime) {                 LuaState L = runtime.getLuaState();                 CoronaLua.newEvent( L, EVENT\_NAME );                 L.pushString(message);                 L.setField(-2, "message");                 try {                     CoronaLua.dispatchEvent( L, fListener, 0 );                 } catch (Exception ignored) {                 }             }         } );

This code when run from any thread (including UI thread), would schedule message to be sent to Lua

Note, that in both cases, code is not immediately executed. It would “wait it’s turn” to be executed on appropriate thread.

To make users more conscious of this we have a bunch of comments around.

EDIT:

Couple remarks:

  • you can see that both cases use runtime to get “scheduler”. It is a good practice to check fi runtime still alive when running on UI thread (It’s in example code).

  • iOS/macOS has very similar mechanism. There all UI and Lua interactions must be ran from “Main” thread, both on same thread. Be careful, since many notifications can come on different threads.

This can be done in several ways:

dispatch\_async(dispatch\_get\_main\_queue(), ^{ ..... });

or

[self performSelectorOnMainThread:@selector(myMethod) withObject:nil waitUntilDone:NO];

or

[[NSOperationQueue mainQueue] addOperationWithBlock:^ { ..... }];

or others, including Swift’s (If you’ll manage to bridge Swift with Lua’s C)

DispatchQueue.main.async { .... }

Sorry, I meant to write back after I read this. Thanks for your detailed and informative reply. It explains it perfectly. Now it makes sense. Thanks so much!

Dear John, 

I have seen the same comments at the code. I really don’t know about what it really mean. I figure it is to let developer known that this functions or methods are called directly from Lua, not from inner Android. But I’m not sure.

I’m testing too with the code.

Have you already discovered how the ‘myTest’ expression can call to the functions at native java? There is any require at the lua code.

I have replaced the myTest for other words and an error occurs.

myTests.printTableValuesXY({ x = 1, y = 2, z = 3 }) myTests.printTableValuesXY({ x = "I'm all alone." }) function onCall() print("callLuaFunction() has succeeded") end myTests.callLuaFunction(onCall)

There is not ‘require’ at the beginning of the lua code.

I can’t figure how native code can link the myTest expression with the functions.

Have you any idea?

Regards from Spain,

Hey!

So, Android have a tendency to run multiple threads. Those are parallel units of execution, and you cannot, say Invoke Lua from other thread than one which runs Lua, because then you can (and will) get situation when you interrupt Lua in undefined state to execute your code and it will break both currently executing code and your code.

Same goes for Android UI - all interactions with Android UI should be performed when no other Android UI interactions are performed, i.e., on UI thread.

So, for that reason there are execution queues. Those are pieces of code, you can send to be executed on separate thread. With UI and Lua - specific threads.

There are examples provided in Native for both cases. My favourite example is in Project Template. First - 

activity.runOnUiThread(new Runnable() {     @Override     public void run() { .........     } });

This allows to start some UI from Lua thread. It would run … on UI thread, allowing to create new widgets etc.

Another example is 

        CoronaEnvironment.getCoronaActivity().getRuntimeTaskDispatcher().send( new CoronaRuntimeTask() {             @Override             public void executeUsing(CoronaRuntime runtime) {                 LuaState L = runtime.getLuaState();                 CoronaLua.newEvent( L, EVENT\_NAME );                 L.pushString(message);                 L.setField(-2, "message");                 try {                     CoronaLua.dispatchEvent( L, fListener, 0 );                 } catch (Exception ignored) {                 }             }         } );

This code when run from any thread (including UI thread), would schedule message to be sent to Lua

Note, that in both cases, code is not immediately executed. It would “wait it’s turn” to be executed on appropriate thread.

To make users more conscious of this we have a bunch of comments around.

EDIT:

Couple remarks:

  • you can see that both cases use runtime to get “scheduler”. It is a good practice to check fi runtime still alive when running on UI thread (It’s in example code).

  • iOS/macOS has very similar mechanism. There all UI and Lua interactions must be ran from “Main” thread, both on same thread. Be careful, since many notifications can come on different threads.

This can be done in several ways:

dispatch\_async(dispatch\_get\_main\_queue(), ^{ ..... });

or

[self performSelectorOnMainThread:@selector(myMethod) withObject:nil waitUntilDone:NO];

or

[[NSOperationQueue mainQueue] addOperationWithBlock:^ { ..... }];

or others, including Swift’s (If you’ll manage to bridge Swift with Lua’s C)

DispatchQueue.main.async { .... }

Sorry, I meant to write back after I read this. Thanks for your detailed and informative reply. It explains it perfectly. Now it makes sense. Thanks so much!