Does NativeScript on Android support calling runOnUIThread()


#1

Hi,

Has anyone tried using runOnUiThread() on a NativeScriptActivity (handle obtained via AppLifecycleCallbackHandler). It seems that in nativescript app the UI thread event queue is not being processed, possibly because the UI thread is doing JavaScript/V8 engine execution which never yields to check its event queue or something like that. I am using a third-party Android Java library that leverages runOnUIThread on current activity to show a android.app.Dialog UI.

All suggestions are welcome. Thanks.


#2

Hey @sny2k8, I am one of the engineers who work on the Android Runtime, and will be happy to answer any questions or concerns you may have regarding the execution flow.

The ART (Android Runtime)/Dalvik runs your Android application which hosts the V8 Virtual Machine within. The V8 runs on the main thread, also known as the UI thread, and will execute javascript operations synchronously if nothing else is blocking the thread. Whenever a script completes executing, the UI thread will either go idle, or execute the next action in the event queue - be it process another javascript instruction as a result of a V8 callback, or run pure Java code.

However what you seem to be experiencing is some sort of deadlock, though we’ve not tested against runOnUIThread specifically, to be able to confirm that it is indeed a problem. Do you have a sample app uploaded somewhere on Github?


#3

Thanks @Pete.K. It is a bit involved and for IP reasons I don’t have the code that I can share.

Let me describe the logistics and hopefully that gives you enough info to verify. To begin with, I have defined a custom application as per NativeScript docs. In onCreate(), there is a call to register the callback handler:

//application.android.js
class Application extends android.app.Application {
public onCreate(): void {
super.onCreate();
this.registerActivityLifecycleCallbacks(com.x.y.AppLifecycleCallbackHandler.getInstance());
}

}

The AppLifecycleCallbackHandler holds a reference to the current foreground activity.

Next, we install an OkHttp interceptor to handle auth challenges from the API endpoint. In the interceptor intercept() method, we get the current activity handle from the callback handler singleton, and then proceed to do as follows:

	currentActivity.runOnUiThread(new Runnable() {
		public void run() {
                           mActiveDialog = new CustomDialog(currentActivity);
                           mActiveDialog.setWebViewListener(...somecodehere...);
                           mActiveDialog.setOnDismissListener(...somecodehere...);
                          mActiveDialog.show();
                   }
	}

The CustomDialog extends android.app.Dialog. There is nothing special there. Note, all this flow works fine in a pure Java Android app.

Hopefully that gives you enough info to create your own small repro.

Thanks.


#4

@sny2k8 OkHttp interceptors run on a background thread, which is ok, but the moment they try to use the main thread:
currentActivity.runOnUiThread(new Runnable() {...} it’s not only possible, but probable there will be a deadlock.
We already had this experience with this issue in the android runtime when using the ACRA library.
I’m really interested in finding a solution for this, as this issue has become more frequent.


#5

I put the app in debugger and can confirm that the runOnUIThread() is working fine. The Runnable.run() method is getting executed (inline, everything is happening in the main thread) and it goes all the way to the call to dialog.show() and then nothing happens. Looks to me that the deadlock may not be the issue. The custom dialog (implemented in native Java code) contains android.webkit.WebView (only) for which content is loaded from a URL at runtime. Could adding a custom activity in some fashion help with the dialog placement (instead of current attempt of putting it in the built-in nativescript activity)?

Thanks.