I’m writing a cross platform (Android and Windows) application and came across something that I can’t find an answer to.
I want to save my preferences file and free some objects when my app closes. For the Windows platforms the OnClose OnDestroy and unit Finalization all work as expected but as far as I can tell they never fire in the Android application.
OnCreate and OnShow do seem to work in Android like they do in Windows.
I did find OnSaveState, but that seems to fire both when the app loses (or regains ?) focus as well as when it closes.
What is the best way to save files and clean up memory when an Android app closes? Do I even need to bother freeing objects I created that exist for the whole application run time?
In my application the IDE allocates FormCreate(Sender: TObject) to OnCreate and FormDestroy(Sender: Tobject) to OnDestroy.
I have had no noticeable problems with FormDestroy but on Android I find that if I want to do things in form create like populate ComboBox options out of a database I have to do that in a FormCreateComplete function which is fired by a TTimer action. I understand that this is because Android somehow has a delayed form build and not all components fully exist at FormCreate. (I do not have any confidence in this analysis I just found a delayed “Completion” of FormCreate fixed the problem so that is my goto solution when these problems happen. )
Why do you believe they are not firing? Is this based on a break point in OnDestroy not breaking?
In the past no break points worked on my “cheap” Samsung. Support told me my phone was “too slow”. Recently they did start working again on that phone maybe due to a phone update but I am vaguely aware that maybe a breakpoint in “ondestroy” might have been missed on that phone. I assumed the destroy functionality worked just my “too slow” phone did not catch the break.
I have had the problem where some of my code is not executed.
Debugging from an earlier known point helped my find this bug. I have thought about reporting the problem but cannot always reproduce it.
Anyway try deleting the dcu’s and building your project.
FormDestroy for the main form may never be called. Same goes for OnSaveState. Why? Because for example, “force stopping” an app does not do a graceful shutdown of the app - it just forcibly removes the app (like a crash, but no actual crash).
One possibility is to use the WillTerminate application event, though I recall times when even this may not occur. It’s still far more reliable than using OnDestroy.
A better measure to ensure that anything you want to possibly restore when the app starts again, is to persist it at the first available moment, e.g. for preferences: as soon as they are changed.
Yeah, that seems to be the way forward with settings (saving them as they change). I’m guessing that this is just how Android works. You don’t really have any control over the app being closed, so you need to assume it could close at any moment without notice or opportunity to take any action.
If that’s the case then, for cross platform apps I guess you can still code the object cleanups but assume they will only be enacted on Windows. Freeing short term objects (that are no longer required) is still required of course to stop memory usage creep.
This and other issues I’ve had to deal with seem to be missing from the video tutorials that I’ve watched so far. It’s now apparent (to me) that the mobile environment is quite different to what I’m used to in Windows. Maybe @ianbarker can touch on this in a future video?
FWIW, on mobile platforms, and, increasingly on desktop platforms, the pattern is to save the setting change immediately it occurs. Also, where possible, code to an interface to take advantage of auto reference counting and disposal.
On mobile platforms, as you’ve discovered, apps don’t really terminate, as such. This is a blessing and a curse. Even though they don’t really terminate under normal circumstances they also get dumped by the operating system to cope with other circumstances such as low memory.
Personally, on Windows and similar desktop targets, I found that OnCloseQuery is usually a dependable place to tidy up instances. On Mobile, as you’ve found, this event and the OnFormClose doesn’t get triggered most of the time.
My links above are more up-to-date than Paweł’s. You can still download the example code he quotes but, to be honest, it really only contains the code you can see in the code blocks on the post and CC is deathly slow so I wouldn’t worry about it.