Android Question Replicating OnResume errors

awoo060

Member
Licensed User
Longtime User
Hey everyone, sorry if this has been covered somewhere else. I'm having a few odd problems initializing objects after a resume. Failing to do this in the past has caused obvious errors - so onResume I check that everything I need is initialized and if not, reinitialize it.

There is at least one rogue object, that according to the code, SHOULD be initialized but is throwing an error when its child property(s) are referenced.

My question is: is there any easier way to replicate the conditions to produce this error? That is, instead of leaving the app open for hours (overnight) and hoping to catch the error, is there a way to manipulate the app or device to make make it unload some modules from my app and hopefully catch the error that way, without having to wait hours for each try?

Cheers all.
 

KMatle

Expert
Licensed User
Longtime User
See here for the basics: https://www.b4x.com/android/forum/threads/android-process-and-activities-life-cycle.6487/

You could remove views or objects so they are not initialized anymore by code to test the behaviour. But this is not a "good" way. It's much better to initialize everything at one place. Use First_Time, Activity_Pause & Resume to initialize all your objects:

Sub Activity_Create (FirstTime As Boolean)
This sub is called when the activity is created.
The activity is created when the user first launches the application, the device configuration has changed (user rotated the device) and the activity was destroyed, or when the activity was in the background and the OS decided to destroy it in order to free memory.
This sub should be used to load or create the layout (among other uses).
The FirstTime parameter tells us if this is the first time that this activity is created. First time relates to the current process.
You can use FirstTime to run all kinds of initializations related to the process variables.
For example if you have a file with a list of values that you need to read, you can read it if FirstTime is True and store the list as a process variable.
Now we know that this list will be available as long as the process lives and there is no need to reload it even when the activity is recreated.

To summarize, you can test whether FirstTime is True and then initialize process variables.

Sub Activity_Resume and Sub Activity_Pause (UserClosed As Boolean)
Each time the activity moves from the foreground to the background Activity_Pause is called.
Activity_Pause is also called when the activity is in the foreground and a configuration change occurs (which leads to the activity getting paused and then destroyed).
Activity_Pause is the last place to save important information.
Generally there are two types of mechanisms that allow you to save the activity state.
Information that is only relevant to the current application instance can be stored in one or more process variables.
Other information should be stored in a persistent storage (file or database).
For example, if the user changed some settings you should save the changes to a persistent storage at this point. Otherwise the changes may be lost.
 
Upvote 0

somed3v3loper

Well-Known Member
Licensed User
Longtime User
Did you try to call Activity_Resume like calling any other sub ?
Uploading project or some code may help others help you catch the problem .
 
Upvote 0

awoo060

Member
Licensed User
Longtime User
Thanks for the reply guys.
somed3v3loper, yes the current code is doing almost exactly that.

Due to limitations on the transitions between activities, I only actually have one activity, and all other screens which would normally be an activity are just panels. The OnResume for my one activity, looks to see if everything within the app is loaded that should be:


Public Sub Activity_Resume()
If IsAppLoaded = False Then
LoadApp
End If
End Sub

The IsAppLoaded method runs through and checks everything that has previously been loaded, first as being not null, then as being initialized. A snippet looks like this:


public Sub IsLoaded() As Boolean
Dim result As Boolean

result = True
If SvAllData = Null Or SvAllData.IsInitialized = False Then result = False
If SvAllData.Panel = Null Or SvAllData.Panel.IsInitialized = False then result = false

return result
End Sub

So my problem is, how do I know if any given code changes have fixed the issue? It would only appear if my android has taken stuff out of memory, which doesn't tend to happen for a number of hours worth of waiting, which is kind of impractical and a frustrating way to test. If I have fixed my error, its hard to say if my new code was responsible for the fix, or that the android never took anything out of memory and therefore the conditions for the bug were never present.

Ideally for the purposes of confidence moving forward, it would be great to know how to replicate the conditions of this bug :- the device taking views/objects out of memory before a resume - so that I can continually test and log things over and over without having to wait hours and hours inbetween.

Sorry for the length of this explanation, but it gives you the proper context of the question. And thanks for your help!
 
Upvote 0

JordiCP

Expert
Licensed User
Longtime User
The conditions in Activity_Resume are not easy to replicate since one thing is calling the sub and another is what the system has done up to that point.
If you want to replicate conditions where memory has been freed, perhaps the way would be to launch other activities which take system memory.

Anyway, I don't understand one thing
  • You are saying that there are (or there have been) certain situations where objects that have been initialized in Activity_Create, are not initialized when the activity is Paused and Resumed again.

Unless I am missing something, Android will call again Activity_Create, before Activity_Resume, if some memory has been freed. So, for your check to be effective, your isAppLoaded condition should always be true after Activity_Create.
 
Upvote 0

awoo060

Member
Licensed User
Longtime User
Yeah I'm thinking about going down the path of writing a second memory intensive app to help replicate the conditions of the test.
In response to your question, not exactly. There are instances of objects that have been created *from* the Activity_Resume method, but they were not initialized *in* it.

I.e. the Activity resume calls LoadApp where applicable, and this is where all initialization takes place. This call is done in Activity_Resume, as from my understanding at the time, this is *always* called, versus activity_create which is sometimes called. In instances where activity_create is not called, my understanding is that I don't need to make my check, but I do anyway to be as safe and sure as I can be.

Having re-read the process and life cycle thread again:

Activity_Create
"The activity is created when the user first launches the application, the device configuration has changed (user rotated the device) and the activity was destroyed, or when the activity was in the background and the OS decided to destroy it in order to free memory."

Does the Activity_Create method fire *when* the device destroys the activity to free memory? Or when the application is fired up *after* having been destroyed? I would think it is the second scenario, which would give me a good location for some logging where:

Activity_Create

if firsttime = false then
'We must have destroyed the activity while it was in the background
'Do some logging of suspect objects not being initialized.

end if

end sub
 
Upvote 0

JordiCP

Expert
Licensed User
Longtime User
There are instances of objects that have been created *from* the Activity_Resume method, but they were not initialized *in* it.

Of course this and many other things can be done, but they are more likely to give such kind of errors

If it is not too late in your project structure, try to initialize Activity objects in Activity_Create, and init process global variables in the same place if FirstTime=True
 
Upvote 0
Top