Android Application Class Lifecycle

Android Application Class Lifecycle

No. Your entire application can be killed and recreated with the task stack intact; this lets the system reclaim memory on devices that need it while still presenting a seamless illusion of multitasking to the end user. From the docs:

A background activity (an activity
that is not visible to the user and
has been paused) is no longer
critical, so the system may safely
kill its process to reclaim memory for
other foreground or visible processes.
If its process needs to be killed,
when the user navigates back to the
activity (making it visible on the
screen again), its onCreate(Bundle)
method will be called with the
savedInstanceState it had previously
supplied in
onSaveInstanceState(Bundle) so that it
can restart itself in the same state
as the user last left it.

That is, the process (which the Application is tied to) can be killed off but then restarted, and the individual activities should have enough info to recreate themselves from what they've saved before being killed, without relying on global state set in the process by other Activities.

Consider storing persistent shared state that needs initialization by an Activity in either a SharedPreference or SQLite database, or passing it to Activities that need it as an Intent extra.

Android Application class lifecyle documentation

I can't find an official documentation telling me that yes, the Application class can be killed on low memory.

Below are the references to where it's been stated:

  • Application Fundamentals
  • Processes and Threads
  • Multitasking the Android Way

I can't find any official diagram representing the Application lifecycle neither.

This is a reasonable observation... Although the following is opinion-based, my best guess is that such a diagram would contradict the Android's multitasking "philosophy" as described in the last reference provided:

"A key to how Android handles applications in this way is that processes don't shut down cleanly. When the user leaves an application, its process is kept around in the background, allowing it to continue working (for example downloading web pages) if needed, and come immediately to the foreground if the user returns to it. If a device never runs out of memory, then Android will keep all of these processes around, truly leaving all applications "running" all of the time."

I can't find any proper callback to use when the Application class is killed excepted onLowMemory(). Does it mean that I have to use this method to persist my data?

Regarding onLowMemory() whose description is quite straightforward, are we talking about a background process or foreground UI?...

If none of application Activities is in foreground and OS is low on memory, it may kill the app so that none of the Application's or the app component's (Activity, Service) callbacks will be invoked. That said, (since you're dealing with Activities) I recommend to store all persistent data as per the documentation, in onPause().

If the Application class is killed on low memory pressure and the app comes to foreground again, how can I know in its onCreate() that the app has been recreated after a system kill?

You can't recognize it in Application's onCreate().

Application class lifecycle while service is running

  • Regarding the application object:

The application object is the main absolute starting point on any Android app. It will always exist before any of the Manifest declared items such as Activity, Service and BroadcastReceiver. So relax that the singletons will be there for you.

  • Regarding the singleton paradigma:

That's a big discussion topic, you can google more about it so what follows is my personal opinion on it. Whatever is the reason for your singletons (a database, an bitmap caching, a FileUtils) I think it's ok and correct to initialise them on the very first point of entry of your app, which is the Application. But the application itself is not an object meant to carry or hold those objects, that way my suggested design approach is to:

=> on your singleton object/class you'll have to:

private static MySingletonClass instance; // reference to the single object
private MySingletonClass(Context c){ // private constructor to avoid construction from anywhere else
// let's say it needs the context for construction because it's a database singleton
}
public static MySingletonClass get(){ //
if(instance == null) throw new RuntimeException("This singleton must be initialised before anything else");
return instance;
}
public static void init(Context c){ // call the initialisation from the Application
instance = new MySingletonClass(c);
}

=> and then on your Application object you simply init the singleton

onCreate(){
MySingletonClass.init(getApplicationContext());
}

with that way you'll keep the necessary initialisation, enforce the singleton pattern but to access the object you call to that object class not to the application. I know it's just a organisational difference, but I believe that that's what separate good and bad code.

So for example on your service the call is: MySingletonClass.get() and should never be MyApplication.mySingle.

hope it helps.

Why manage lifecycle through Application class?

I don't know, but have just Googled. Check the source.

https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/app/Application.java.

You can see that all this does is call your callback methods, there is no further processing. The comments also indicate that it's designed usage is for handling state persistence.

Therefore, you could achieve the same by creating an Activity base class which provides overrides of the activity callbacks then extend all of your activities from this.

public class BaseActivity extends Activity{
@override
public void onCreate(){
super.onCreate(); // calls the framework method
}
}

public class Activity1 extends BaseActivity{
@override
public void onCreate(){
super.onCreate(); // calls the base method which in turn calls the framework method
...
}
}

public class Activity2 extends BaseActivity{
@override
public void onCreate(){
super.onCreate();
...
}
}

These methods will be called for all activities, regardless of whether they extend a base class. So this class lifecycle will automatically make those callbacks without you having to do anything more. Note that it only extends Activity, not BaseActivity.

public class Activity3 extends Activity{
@override
public void onCreate(){
super.onCreate();
...
}
}

Since you cannot have multiple inheritance in Java,if an activity needed to extend something other than a base class for all activities, you would have to start chaining callbacks which could get messy quickly.

Finally, since ActivityLifecycleCallbacks is an interface, and since you can register multiple implemenations of that interface, you could have one set of callbacks to manage application state, another to manage user state, perhaps one to manage service or resource handling and so on without having to mix that code in a single call back method.

How to determine when Android application is being exited - application lifecycle instead of activity lifecycle

To do this you can use the new Android Lifecycle features. Instead of listening to Activity's Lifecycle just listen to the whole Application's Lifecycle. Just simply create an Application class and add the following code to it:

public class MyApplication extends Application implements LifecycleObserver {
@Override
public void onCreate() {
super.onCreate();
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
}

@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onEnterForeground(){
}

@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onEnterBackground(){
}
}

In your gradle file add this dependency:

implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"

And you should get the effect you need.

How to get Application Lifecycle events in Activities?

If you use the Application class to listen to lifecyle events, BaseActivity can register with the Application class as current Activity in onResume()

@Override
protected void onResume() {
super.onResume();
((App)getApplication()).registerActivity(this);
}

The Application class needs fields

private boolean showDialog = false;
private BaseActivity currentRegisteredActivity = null;

then as soon as an Activity is registered it will be told to show the dialog if the app has been in the background up to now:

public void registerActivity(BaseActivity activity) {
currentRegisteredActivity = activity;
if(showDialog){
activity.showInitialDialog();
showDialog = false;
}
}

The methods for observing the lifecycle events:

@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void appInResumedState(){
showDialog = true;
Log.d(LIFECYLE_EVENT, "appInResumedState: ");
if(currentRegisteredActivity != null){
currentRegisteredActivity.showInitialDialog();
showDialog = false;
}
}

@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void appInPausedState(){
showDialog = false;
Log.d("LIFECYLE_EVENT", "appInPausedState: ");
currentRegisteredActivity = null;
}

Application Class Lifecycle in Android

To maintain global variables, the Application class is extended

You are also welcome to use classic Java static data members.

What happens to these variables when the application is put in the background and at some point, the OS wants to free up the resources?

The only "resources" that "the OS wants to free up" will be your entire process. Your static data members or other singletons (like a custom Application, or your ContentProvider instances) will remain in memory until such time as Android terminates your process.

If the onTrimMemory() call is ignored, then does that mean that all of the variables are preserved?

Yes, until such time as Android terminates your process.

Why extend the Android Application class?

Offhand, I can't think of a real scenario in which extending Application is either preferable to another approach or necessary to accomplish something. If you have an expensive, frequently used object you can initialize it in an IntentService when you detect that the object isn't currently present. Application itself runs on the UI thread, while IntentService runs on its own thread.

I prefer to pass data from Activity to Activity with explicit Intents, or use SharedPreferences. There are also ways to pass data from a Fragment to its parent Activity using interfaces.

Android Application class - lifecycle of field members

there is no onCreate that you can register to.
in later API's there's a way to register to the Activity lifecycle functions. and then you can do what ever you want.

basically, what you should do is use SharedPrefrences for storing information.

what I would do is:

class MyApp extends Application {
private static String someResource = null;
public static String getSomeResource(Context context) {
if(someResource == null) {
SharedPrefrences prefs = (SharedPrefrences)
context.getSystemService(Context.SHARED_PREFRENCES);
someResource = prefs.getString(SOME_RESOURCE, null);
}
return someResource;
}


Related Topics



Leave a reply



Submit