Application restart - Activity Entry Point

2019-01-14 03:38发布

问题:

I have an application where the entry point is let's say a "login/splash" Activity, where I need to pre-load fresh data from the server. This SplashActivity is declared as :

<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

in my AndroidManifest.xml, after data is loaded, I keep some data on my custom Application class and I proceed to my MainActivity.

I am expecting, that after my Application is stopped by the OS or by the user (using Force Stop), and then later is re-started by the user, the entry point of my application to be SplashActivity again BUT the system skips the SplashActivity and displays the MainActivity.

QUESTION: is this the expected behaviour? If the entire process is stopped, shouldn't my application be started with SplashActivity? Can this be accomplished?

回答1:

Actually, there are several problems that are addressed by this question and some of the answers to it:


To answer your original question, "Yes, this is the expected behaviour".

Android considers each Activity to be a separate self-contained entity. Android remembers the state of activities in the task stack and it has no problem killing your process (which contains all your activities) whenever it wants to, because it "knows" that it can always reconstruct your activities whenever it needs to. This concept, of course, breaks down when you have a complex application where you have dependencies between the activities and/or you have global data that you store in an Application class (or similar static/singleton place).

When Android kills your process it remembers the topmost activity in the task and when the user returns to the task it recreates the process and then recreates only the topmost activity in the task. In your case, MainActivity.

As an example, if your task stack looks like this:

StartActivity -> ActivityB -> ActivityC -> ActivityD

and your task goes to the background and Android kills the process, when the user returns to the task only ActivityD will be recreated. Once ActivityD is finished, Android will then recreate ActivityC. Once ActivityC is finished, Android will recreate ActivityB, etc. In short, the complete stack is not recreated when the user resumes the task.

There is no combination of manifest settings or Intent flags that will get you the behaviour that you want. It would be nice if Android offered something like that, but at the moment it does not.


You can determine if your process has been restarted by using a static (class) boolean variable in your Application-derived class (or in any other class). This variable will always have the value false when the process is restarted and you can then check the state of the variable from anywhere and reinitialize (reload your data) if necessary. Then you set the variable to true. It will remain true until the process is killed and recreated, even if all your activities finish. In this way you can initialize only when needed.

You can also use this as an indicator to restart your application from the SplashScreen. So in all your activities, in onCreate(), you can check the state of this boolean variable and if the application has been restarted you can simply redirect to the SplashScreen like this:

Intent intent = new Intent(this, SplashScreen.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

This will finish all the activities in the task and restart the SplashScreen at the root of the task.


Next, if you want to prevent having to download data every time the user returns to the application (when it was in the background and subsequently killed by the AndroidOS), you should store the data that you download in the private cache area and use that when the application is restarted. This prevents having to download the data repeatedly if your process is killed and restarted.


Another way of dealing with this would be to load your data in a Service. If you have a Service running in your process then Android is less likely to kill your process. You just need to make sure that you shut down your Service when the user is finished with your application.


I realize this answer is long-winded. Hopefully you can get something out of it.



回答2:

It can be done like this:

1. SplashActivity will start no doubt every time.

2. Download the data and save the check(boolean) indicating the loading is done previously.You can use SharedPreferences.

3. Check the condition next time and start your MainActivity immediately.