Jump to content
Yaron

When is a Delphi form actually visible to the user on Android?

Recommended Posts

I actually posted this question on stack overflow a while back, got what I thought was a working answer but over time realized that on different devices, waiting for "onIdle" doesn't actually work.

 

Here's the background, my app on first-load does some time-consuming (3-8 sec) pre-calculations so subsequent runs would be much faster.  During this processing period, I want to show a "loading %" track-bar.

 

However, for the life of me, I haven't been able to find the exact moment my form is visible and responsive for action.  I tried different approaches:

1. waiting for "OnActivate" event.

2. Implementing IFMXApplicationEventService.SetApplicationEventHandler and waiting for "TApplicationEvent.BecameActive".

3. Waiting for "TApplicationEvent.BecameActive" to trigger and then waiting for 3 "OnIdle" events to trigger (2 OnIdle events were not enough for my Galaxy Note 4 device).

 

Only #3 sort of worked on most devices using Delphi 10.2.3, but then when I upgraded to Delphi 10.3.1 even that stopped working (my progress bar shows up but the screen stops updating, so the bar remains on 0% until the pre-calculation function completes, even when calling Application.ProcessMessages after each update and no other code running in the background).

 

Is there a better solution to know the exact moment my app will start responding to screen updates on launch under Android?

 

Edited by Yaron

Share this post


Link to post

Just to make sure I understand, this implies I can't do UI updates in my main thread in the middle of a function?

Share this post


Link to post

You can. But it will be drawn after the control is returned to UI.

Edited by Cristian Peța

Share this post


Link to post
9 hours ago, Yaron said:

I actually posted this question on stack overflow a while back, got what I thought was a working answer but over time realized that on different devices, waiting for "onIdle" doesn't actually work.

The answer you were given on StackOverflow suggested you use a background thread, which is what you should be using.

Quote

Here's the background, my app on first-load does some time-consuming (3-8 sec) pre-calculations so subsequent runs would be much faster.  During this processing period, I want to show a "loading %" track-bar.

Start a background thread on app startup to perform your time-consuming work.  Have the thread use TThread.Synchronize() or TThread.Queue(), or simply assign a handler to the TThread.OnTerminate event, to communicate back to the main thread when the background thread is finished.  Have your UI display the trackbar by default, and then hide the trackbar when the background thread is finished.

Quote

However, for the life of me, I haven't been able to find the exact moment my form is visible and responsive for action.

You don't need to in this situation.

Quote

I tried different approaches:

1. waiting for "OnActivate" event.

2. Implementing IFMXApplicationEventService.SetApplicationEventHandler and waiting for "TApplicationEvent.BecameActive".

3. Waiting for "TApplicationEvent.BecameActive" to trigger and then waiting for 3 "OnIdle" events to trigger (2 OnIdle events were not enough for my Galaxy Note 4 device).

The OnIdle event is triggered whenever the main message loop receives a new message and then finishes processing all pending messages.  Don't rely on the timing of that event to drive your app's logic.

Quote

Only #3 sort of worked on most devices using Delphi 10.2.3, but then when I upgraded to Delphi 10.3.1 even that stopped working (my progress bar shows up but the screen stops updating, so the bar remains on 0% until the pre-calculation function completes, even when calling Application.ProcessMessages after each update and no other code running in the background).

Application.ProcessMessages() is broken in 10.3.  You shouldn't be using it at all anyway.  Do the pre-calculation in a background thread, and have the background thread post status updates to the main thread as needed.  Let the main thread update the UI on its own schedule.

 

Edited by Remy Lebeau
  • Like 1

Share this post


Link to post

Something weird happened in the post above, I can't edit it for some reason.

I tried doing the pre-calculations in a thread, but it resulted in instability. what I'm doing is resizing graphic elements and I simply can't get TBitmap to work without throwing exceptions in a thread on Android.

Share this post


Link to post
4 hours ago, Yaron said:

 tried doing the pre-calculations in a thread, but it resulted in instability. what I'm doing is resizing graphic elements and I simply can't get TBitmap to work without throwing exceptions in a thread on Android.

TBitmap works in a thread, so you are probably just not using it correctly.

 

But, if threading is not an option, then I suggest to break up your calculations into small chunks that you can execute asynchronously without blocking the UI thread, such as with TThread.ForceQueue(). Execute a chunk and queue the next chunk, then return to the main message loop. When ready, the next chunk will execute, queue the next chunk, return to the main message loop, and so on, until the calculations are finished.

  • Like 1

Share this post


Link to post
10 hours ago, Yaron said:

I tried doing the pre-calculations in a thread, but it resulted in instability. what I'm doing is resizing graphic elements and I simply can't get TBitmap to work without throwing exceptions in a thread on Android.

As far, as I know, TBitmap had problems with threads in Tokyo. In Rio it should be fine.

Edited by Микола Петрівський

Share this post


Link to post

The last time I suffered from TBitmap threading instability was in v10.2, so perhaps that's been resolved.

Share this post


Link to post
On 4/11/2019 at 5:15 AM, Yaron said:

The last time I suffered from TBitmap threading instability was in v10.2, so perhaps that's been resolved.

Multi-threading issues for TBitmap were addressed in 10.2 Tokyo:

http://docwiki.embarcadero.com/RADStudio/Tokyo/en/What's_New#Multi-Threading_Support_for_TBitmap.2C_TCanvas_and_TContext3D

Edited by Remy Lebeau

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×