Note: While the two answers provided so far (on September 6th) are interesting, they unfortunately don't address the question.
One of my Android test devices is a HTC One X. This device is known for frequently killing background applications (even including the launcher, most infuriatingly) because it tends to live on the edge in terms of RAM allocation, presumably due to HTC bloatware. However, for my purposes, this has been extremely useful as it has helped to highlight the effects of various low memory situations and allow me to improve my application to cope with such events. One of the things I have learnt, for instance, is that the Application
instance and other static
resources can be killed even though the Activity
backstack is retained. So, to give a good user experience, the backstack can remain even though the single process running the application, and all the static
s it holds, has gone. For this reason, my application is now very rugged in terms of gracefully checking the state, and actioning the re-initialization if necessary, of the "Singleton" data it needs on the resuming of any Activity
.
To move onto my specific question, I have been seeing a rare symptom that, through code inspection, I believe could only have been caused by a static
member of one class having been killed and then subsequently re-initialized, while another static resource in one of my library classes has not been re-initialized. I appreciate that such a dependency between two separate static
resources represents bad design on my part, and I will refactor to avoid this. However, I would like to know if I could possibly be correct in my analysis - that is, is it possible to have a sitation where the backstack is retained, but only some static
resources are killed, particularly on a per-library / package basis?
Edit 1 I'll give a bit more information about the two classes concerned.
Class 1 is a class we'll call Controller
. It's not used as a Singleton, but contains a static
Map
of data to be common across all instances. It's initialised like so:
private static Map<String, String> sSomeMetaData;
static {
sSomeMetaData = new HashMap<String, String>();
}
Next, I have a class called MyFlyweightFactory
. This class lives in a separate library. This class is a Singleton:
private static MyFlyweightFactory instance = new MyFlyweightFactory();
public static synchronized MyFlyweightFactory getInstance(){
return instance;
}
private MyFlyweightFactory(){ }
TreeMap<String, MyParserRenderer> images = new TreeMap<String, MyParserRenderer>();
Now, here is the dependency. The factory class has a getter method to obtain a certain named image object which is constructed by parsing a file from the file system. If the factory hasn't been asked for that image since factory initialization, it parses it from an file (it's actually an SVG image parser library of mine). The image is parsed into a MyParserRenderer
object. When this image parsing happens, the factory also populates some data in the Controller
class' sSomeMetaData
member. All of the images that the factory holds onto are kept in the images
member TreeMap
you see above. So, these images are a non-static member of a static
Singleton factory instance.
The rare problem situation seems to be that instances of Controller
find that sSomeMetaData
is empty, even though I know that MyFlyweightFactory
has provided some objects from its Map
. This could surely only happen, I believe, if the intance of MyFlyweightFactory
has stayed around and therefore didn't need to re-parse the image objects (which means that it will not populate sSomeMetaData
ever again), but in the meantime the static
initializer of Controller
has since executed again. I can confirm that sSomeMetaData
is not being clear()
ed anywhere else in code.
You should take a look at this: Activity lifecycle.
When you are out of memory, paused activities will be killed to free memory.
Hence why you should try and account for this in every situation that you have to re-create the activity.
This is not a whole app, but on an activity basis. So it will start killing activities that it feels are less important. Some activities may be affected, others not, in the same app.
Note the "Killable" column in the above table -- for those methods that are marked as being killable, after that method returns the process hosting the activity may killed by the system at any time without another line of its code being executed. Because of this, you should use the onPause() method to write any persistent data (such as user edits) to storage. In addition, the method onSaveInstanceState(Bundle) is called before placing the activity in such a background state, allowing you to save away any dynamic instance state in your activity into the given Bundle, to be later received in onCreate(Bundle) if the activity needs to be re-created. See the Process Lifecycle section for more information on how the lifecycle of a process is tied to the activities it is hosting. Note that it is important to save persistent data in onPause() instead of onSaveInstanceState(Bundle) because the latter is not part of the lifecycle callbacks, so will not be called in every situation as described in its documentation.
I think you are somehow on the wrong track in debugging or tracing the problems in your Application.
Here is what I can tell you, and what I think that you understood wrong :
When your application is destroyed by Android
because it needs resources, your Application
class will be also "destroyed/stopped" and the backstack
retained. When you re-launch your application, your specific Application
class will be 're-created' (onCreate()
will be called) , and your Activity
back stack, will also be re-created, this meaning that the last Activity
that was visible to the user will be re-created. So basically, what happens in your application, is the expected behaviour. Why some members in a library don't get re-initialized... I can't figure it out.
I also had a similar question here : Application restart - Activity Entry Point
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With