Android Tutorial Android Process and activities life cycle

New video tutorial:



Lets start simple:
Each B4A program runs in its own process.
A process has one main thread which is also named the UI thread which lives as long as the process lives. A process can also have more threads which are useful for background tasks.

A process starts when the user launches your application, assuming that it is not running already in the background.

The process end is less determinant. It will happen sometime after the user or system has closed all the activities.
If for example you have one activity and the user pressed on the back key, the activity gets closed. Later when the phone gets low on memory (and eventually it will happen) the process will quit.
If the user launches your program again and the process was not killed yet the same process will be reused.

A Basic4android application is made of one or more activities. Android support several other "main" components. These will be added to Basic4android in the future.

Activities are somewhat similar to Windows Forms.
One major difference is that, while an activity is not in the foreground it can be killed in order to preserve memory. Usually you will want to save the state of the activity before it gets lost. Either in a persistent storage or in memory that is associated with the process.
Later this activity will be recreated when needed.

Another delicate point happens when there is a major configuration change in the device. The most common is an orientation change (user rotates the device). When such a change occurs the current activities are destroyed and then recreated. Now when we create the activity we can create it according to the new configuration (for example, we now know the new screen dimensions).
How do we handle it? :confused:
When you create a new activity you will start with the following code template:
B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

End Sub

Sub Activity_Create(FirstTime As Boolean)
 
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
Variables can be either global or local. Local variables are variables that are declared inside a sub other than Process_Globals or Globals.
Local variables are local to the containing sub. Once the sub ends these variables no longer exist.
Global variables can be accessed from all subs.

There are two types of global variables.
Process variables and activity variables.

Process variables - These variables live as long as the process lives.
You should declare these variables inside sub Process_Globals.
This sub is called once when the process starts (this is true for all activities, not just the first activity).
These variables are the only "public" variables. Which means that they can be accessed from other modules as well.
However, not all types of objects can be declared as process variables.
All of the views for example cannot be declared as process variables.
The reason is that we do not want to hold a reference to objects that should be destroyed together with the activity.
In other words, once the activity is being destroyed, all of the views which are contained in the activity are being destroyed as well.
If we hold a reference to a view, the garbage collector would not be able to free the resource and we will have a memory leak.
The compiler enforces this requirement.

Activity variables - These variables are contained by the activity.
You should declare these variables inside Sub Globals.
These variables are "private" and can only be accessed from the current activity module.
All objects types can be declared as activity variables.
Every time the activity is created, Sub Globals is called (before Activity_Create).
These variables exist as long as the activity exists.

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.

Activity_Resume is called right after Activity_Create finishes or after resuming a paused activity (activity moved to the background and now it returns to the foreground).
Note that when you open a different activity (by calling StartActivity), the current activity is first paused and then the other activity will be created if needed and (always) resumed.

As discussed above Activity_Pause is called every time that the activity moves from the foreground to the background. This can happen because:
1. A different activity was started.
2. The Home button was pressed
3. A configuration changed event was raised (orientation changed for example).
4. The Back button was pressed.

In scenarios 1 and 2, the activity will be paused and for now kept in memory as it is expected to be reused later.
In scenario 3 the activity will be paused, destroyed and then created (and resumed) again.
In scenario 4 the activity will be paused and destroyed. Pressing on the Back button is similar to closing the activity. In this case you do not need to save any instance specific information (the position of pacman in a PacMan game for example).
The UserClosed parameter will be true in this scenario and false in all other. Note that it will also be true when you call Activity.Finish. This method pauses and destroys the current activity, similar to the Back button.

You can use UserClosed parameter to decide which data to save and also whether to reset any related process variables to their initial state (move pacman position to the center if the position is a process variable).

A new module is available for handling the UI state: http://www.basic4ppc.com/forum/basi...ging-android-applications-settings-state.html

Now you should be ready for this short quiz:
http://www.basic4ppc.com/android/fo...-the-bug-process-activities-life-cycle.37899/
Life cycle graphical diagram: http://www.basic4ppc.com/android/forum/threads/graphical-life-cycle-of-a-b4a-activity.40515/

Starting from v5.20 there is a new feature named Starter Service that acts as a single program entry point: https://www.b4x.com/android/forum/threads/starter-service-consistent-single-entry-point.57599/
 
Last edited:

Alberto Michelis

Well-Known Member
Licensed User
I have a problem with Process_Globasl variables.
May be I dont understand well

I have a Main Activity in which I manage the billing addin, the upgrade fo the db, and all sort of init process of the app.
This Main activity is never called again.
It has many Process_Global variables that are used for many other activitys and by a Service.
This is the first time I realized it but once the app was in the background a lot of time, and I restore, it these variables are blanked.

What am I doing wrong?
 

ilan

Expert
Licensed User
I have a problem with Process_Globasl variables.
May be I dont understand well

I have a Main Activity in which I manage the billing addin, the upgrade fo the db, and all sort of init process of the app.
This Main activity is never called again.
It has many Process_Global variables that are used for many other activitys and by a Service.
This is the first time I realized it but once the app was in the background a lot of time, and I restore, it these variables are blanked.

What am I doing wrong?

After a while an activity goes to the background android will kill it so its importent to store your variables

so if you send an activity to the background and dont use it again and you exit the second activity and return to it (returning to your app will open the last activity so activity 2) the variables in activity 1 may be blank thatswhy you should after starting your 2nd activity from activity 1
get all variables you need and store them in activity 2

if you use a service you better save your data (Process_global variables) to a text file and read from it in your service module...
 

Alberto Michelis

Well-Known Member
Licensed User
But in the first post of this thread, Erel said that Process_Globals are process variables and are alive till the process is killed and, this time, the process is not killed, only the activity is in the backgound.
Besides it works ok during the day, but it olny happened when it is a long time in background.
 

ilan

Expert
Licensed User
Last edited:

Alberto Michelis

Well-Known Member
Licensed User
Then you mean there are not Process Global variables that are accessed by all activities?
This is not true, Im using these Process variables and work ok.
I only have this problem when the app is a long time in backgroud.
 

ilan

Expert
Licensed User
Then you mean there are not Process Global variables that are accessed by all activities?

Where do you see in my answers what you wrote??

I just try to help and if you would click on the link i have posted above you would not keep asking...
 
Last edited:

Alberto Michelis

Well-Known Member
Licensed User
I did, but I dont understand what you think I will find in that link, english is not my mother tong so I´m slow to undestand.
 

corwin42

Expert
Licensed User
I did, but I dont understand what you think I will find in that link, english is not my mother tong so I´m slow to undestand.

Your problem is that you have to understand that your app can start with every Activity, not only with the first one.

When your app is sent to the background it is possible that the system decides to kill the process completely. If you return to your app, it will be started with the activity which was last active. Because the initialization of the process global variables is only in your first Activity they will be emty.

You will need to do global initializations in all of your Activities.
 

aeric

Expert
Licensed User
I have a problem with Process_Globasl variables.
May be I dont understand well

I have a Main Activity in which I manage the billing addin, the upgrade fo the db, and all sort of init process of the app.
This Main activity is never called again.
It has many Process_Global variables that are used for many other activitys and by a Service.
This is the first time I realized it but once the app was in the background a lot of time, and I restore, it these variables are blanked.

What am I doing wrong?
My guest of your issue is how you load the layout in Main activity and calling the variables you have declared in Main activity in your Second activity.
Here is how I normally do:
First, declare some global variables in Main activity Sub Process_Globals
B4X:
Sub Process_Globals
    Dim DBFileDir As String
    Dim DBFileName As String
    Dim DB1 As SQL
End Sub
In Main activity, initialize the variables
B4X:
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("frmMain")
    If FirstTime Then
        DBFileDir = File.DirDefaultExternal
        DBFileName = "mydata.db"
        If File.Exists(DBFileDir, DBFileName) = False Then
            DBFileDir = DBUtils.CopyDBFromAssets(DBFileName)
        End If
        DB1.Initialize(DBFileDir, DBFileName, False)
    End If
End Sub

When you want to call your variables in Second activity, you need to write the activity module, "dot" then your variable.
B4X:
Sub Process_Globals
    Dim DB2 As SQL
End Sub
B4X:
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("frmSecondActivity")
    If FirstTime Then       
        DB2.Initialize(Main.DBFileDir, Main.DBFileName, False)
    End If
End Sub
I always put the Activity.LoadLayout outside or before the "If FirstTime Then"
 

aeric

Expert
Licensed User
One more thing is, DO NOT use "Activity.Finish" to unload the Activity when you want to Start another Activity.
B4X:
Activity.Finish
 
Top