Home » Android » android – static variable reinitialization on M but not on L due to Application onCreate() called more than once

android – static variable reinitialization on M but not on L due to Application onCreate() called more than once

Posted by: admin May 14, 2020 Leave a comment

Questions:

I have an application which has a class derived from the Application class and have noticed that its onCreate() method is being called multiple times. In addition to this the value of its static variables is being reset each time onCreate() is called.

This behavior only occurs on M, it does not occur on L. I am trying to find out if its a bug in M or an intended change in M or there is some fundamental inherent problem with the app architecture which has lain dormant and only now manifested with M.

The Application derived class’s onCreate() is being called whenever a broadcast receiver’s onReceive() is called.
Multiple instances of the Application class are NOT being created – onCreate() is being called on the same object instance, and the same application context is present throughout.

Here’s some code snippets demonstrating this observation:

public class MyApplication extends Application
{
    public static int debugVal = 5;

    public MyApplication ()
    {
        theApp = this;
    }

    public void onCreate ()
    {
        Log.v(TAG, "++++++++++++ onCreate() debugVal: " + debugVal);
        debugVal = 10;
        ....



public class MyBroadcastReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive (Context context, Intent intent)
    {
    Log.v(TAG, "onReceive. debugVal: " + MyApplication.debugVal);
    ...

When run on Marshmallow the logcat output is:

831-1412/? I/ActivityManager Start proc 2244:com.company.redacted/u0a86 for broadcast com.company.redacted/com.company.redacted2.MyBroadcastReceiver
2244-2244/? V/MyApplication: ++++++++++ onCreate() debugVal: 5
2244-2244/? V/MyBroadcastReceiver: onReceive. debugVal: 10
...
831-1327/? I/ActivityManager: Start proc 3271.com.company.redacted/u0a86 for broadcast com.company.redacted2/com.company.redacted1.MyBroadcastReceiver
3271-3271/? V/MyApplication: +++++++++++ onCreate() debugVal: 5
....

See how onCreate() is called more than once, and how debugVal has lost its value of 10 by the second time onCreate() has been called.
When the same .apk runs on Lollipop the second call to onCreate() is not present.

The log on L looks like this:

768-783/? I/ActivityManager: Start proc 2480:com.company.redacted/u0a84 for broadcast com/company.redacted1/com.company.redacted2/MyBroadcastReceiver
2480-2480/? V/MyApplication: +++++++++++ onCreate() debugVal:5
2480-2480/? V/MyBroadcastReceiver: onReceive. debugVal: 10
....
2480-2480/com.company.redaced1 v/MyBroadcastReceiver: onReceive. debugVal: 10

I’d like to know what’s going on and eliminate it, but if I can’t is it going to be possible to replace the Application class with some singleton class whose static variables are guaranteed to be safe and reliable and initialized only once?

This is a pre-installed app which starts on boot (which is one of the intents the receiver listens to) and doesn’t have any Actives at this point.

How to&Answers:

You say onCreate() is being called twice in the same process but that’s probably incorrect. It’s very possible that Marshmallow is more aggressive about killing your process, either because less memory available or just being more aggressive about killing idle packages (see this issue for mention of ’empty #17′ and the docs mentioning CACHED_EMPTY).

To verify, make your service a foreground service by calling startForeground with a persistent notification. If your problems disappear it means the OS was killing your process.

In general you shouldn’t rely on staying running in the background – make initializations as lazy and fine-grained as possible, and make background operations like broadcast receivers as cheap as you can.

Answer:

Notice that in log messages you’ve shown, the whole process is restarted, and hence onCreate is called again, can you describe what happens between the two events, or some details on what you application is doing and what can trigger the killing of the first process and starting a new one?

Answer:

Static variables are bad for holding state. The reason for this that static variables don’t survive across lifecycle and app starts/shutdowns. You generally only use static variables for constant state. Which means variables that have the same initial value or are constants.

If the value is changing then it should be stored in storage such as Prefs.


As for why you are getting multiple calls to OnCreate; could you elaborate what kind of BroadcastReceiver you are implementing?

It is possible that an incoming intent could be causing a configuration change which would destroy and recreate the Application.