Suppose I have a reference to an instance of a class, which doesn't have any direct/indirect reference to problematic objects (like context,views,...). Are there any differences between using this reference in a static reference and using it inside the class that extends the Application class?
I mean, in both ways the referenced object will be freed only when the process is killed (or when there are no references to it), right? Maybe there is a difference when using multiple processes?
One slight difference is that the Garbage Collector will first destroy static references bound in Activities (or Services) in case of intense memory shortage if it was in a situation of choosing between a static reference and a reference inside Application class. This situation happens because when the Activity (or Service) is destroyed, it will leave the static variables without references (if they have no other reference except the one described above), so they can be collected by the GC. Even if the VM reinitialize the Activity (or Service), those static references will take the initial value losing any updates that may have been occurred. As a general rule of thumb, if you want to be sure that the static variables will be persistent:
Do not reference them from Activities (or Services) since there is a chance that they might be destroyed in case of memory shortage.
Reference them from Activities or Services but handle the situation of them being destroyed manually (for example, with the onSavedInsanceState method of Android) just like will you do with non static references.
EDIT Here is an explanation of why is this happening:
Static references are bound to the class loader of the class
that first initialized them. This means that that if a static variable
inside any class has been initialized by an activity, when that
activity is destroyed also its class might be unloaded and so the
variable becomes uninitialized. While if the variable is initialized
by the application class, it’s life is the same as the application
process so we’re sure that it will never become uninitialized again.
That’s why I chose to initialize all the singletons in the
MyApplication class.
found in this link.
I believe the article cited in the other answer by #Angelo is very wrong (to say the least) and caused much confusion : the classes in android are unloaded on a per process basis not on a per class basis. That is if your app is killed and the classes are unloaded you lose all static state - if not no. That is what I make of #fadden's answers at least :
Is it still the case that Android never unloads classes?
Android: When do classes get unloaded by the system?
Now your question is a bit vague... A static reference is not the same as a non static wherever it's used. If you mean that both variables are static then there is no difference if they are in an activity, application or whatever instance - whenever the class is loaded and the variables take some value they will remain so till the classes are unloaded. Not sure if there is a specified order in unloading the classes - or if that would matter.
Related
"Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)" is shown while making any Android control static. Any better way to access an android control(like TextView) from other class other than creating an object of Parent class or making it(TextView) static?
I'm not sure if what you are doing is valid, but you can use an event bus, such as Otto to send events from objects to objects (such as from a Service to an Activity)
And you can have your own Application-derived object, this will be a singleton existing all the time while your program is alive, so you can have static fields in there.
As we know, the Application or MultiDexApplication class always remains active in memory, so we do not need to make our objects or variables as static, instead just declare them as normal(non-static) one, and call by creating an object of that application class, ie. instead of calling it directly as a static..
Wrong Way:
AppClass.myObj = 1;
var = AppClass.myObj;
Right Way:
AppClass appClass = (AppClass)getApplicationContext();
appClass.myObj=1;
and
var= appClass.myObj;
I'm new to Android (and Java) and was trying to find out where to store my global variables that I need in my various Activities, Fragments, etc. so I can easily access them, as well as saving and restoring them when the app is paused (a process that not yet fully understand, but that is not my question).
So the general consensus seems to be to use Singletons by extending Application (like described here).
Now that I played around some more I was wondering what is the reason against declaring variables in the main activity (e.g.final static int myVariable) and then accessing the variable trough MainActivity.myVariable? What is the downside?
Thank you in advance!
First, consider to design your app without needing global variables in the first place. Using global state variables might seem like an easy solution at first, but will complicate testing and maintenance later.
If you absolutely must, the application class is the correct place because it's lifecycle is your application's lifecycle. You can also use regular member variables instead of statics.
If you store variables in an activity class as static variables, the downsides include but are not limited to:
Loading another activity class needs to load all the code in the main activity as well.
Unnecessary dependency from activity to another, creating increased coupling.
statics are harder to mock/inject for example in a testing setup. A thin application object with member vars is easier to mock.
You can make a class that is subclass of Application, and scope of this class will be application wide, so you can access variable globally ( across the activities/fragment)
here you will get related info
there is no downside declaring your global variable as static unless the variable is bound to Context...
it is bad way to maintain static reference for Context (like Activity, Service), Views, Drawables and application Resources...
and some one said in SO (I didn't remember), Android will clear static memory in low memory situations...
For example if you are in "FirstActivity" that calls "SecondActivity", using startActivityForResult, to add a Product do a list, in "SecondActivity" you can CANCEL or ADD this product, if you ADDED it you whant to refresh the Product's list in "FirstActivity" so in "SecondActivity" you can use a "private static final int ADDED = 1" and a "private static final int CANCELED = 2" and pass one of this attributes in the setResult's method of "SecondActivity", before call the finish method, in FirstActivity's "onActivityResult" method you can verify if the "resultCode" is "SecondActivity.CANCELED" or "SecondActivity.ADD" and performe the list's refresh or not.
Just an example..
You can use Application's class (OS save variable in memory while app not destroy) or SharedPreferences (OS save variable to file permanent).
Initially I didn't pay a lot of attention to the possibility of memory leaks in Android, given the nature of managed code / garbage collection and so on. I'm thinking this might have been a bit naive. Here's the question:
Say there is an activity - MyActivity. When the OS starts it, in its onCreate() this instantiates another class (MyOtherClass) and keeps a reference to it. However say the instance of MyOtherClass also keeps a reference to the context - which happens also to be a reference to the instance of MyActivity.
Now something happens - say the screen gets rotated. OS calls the activity onDestroy() and drops the reference to that old instance of MyActivity. However, that activity instance still has a reference to an instance of MyOtherClass, which in turn has an instance to the activity.
So, am I right in thinking those two classes are going to keep each other alive for evermore?
If so, I guess possible answers are (a) don't keep a context reference, get it another way, or (b) in the activity onDestroy() drop any references it has to anything else, then it all ought to just collapse.
Java wouldn't allow cyclic links to keep each other alive (in memory). However if you have declared references static or created singleton style objects, Java won't help you there.
A good start might be reading avoiding memory leaks.
I have an android application with a number of activities.
I have a singleton class holding my main data model which all activities access to get data.
The problem is that sometimes the android GC decides to destroy my singleton when the app in the background (when you press the home button).
Is there anyway that I can bypass this?
I've had this exact problem in a current application of mine, which needs to retain a large amount of data in various 'singleton' classes. The problem I encountered was as in your case; i.e. sometimes when bringing the application back to the foreground, some of the static 'singleton' classes have been destroyed.
The problem, I believe, is that the 'lifetime' of such classes can never be well defined or predicted. After all, it's a class sat there holding a reference to itself, so it's susceptible to being garbage collected when the system wants to grab some resources.
You're probably already aware that extending android.app.Application is a well-known alternative to using conventional Singletons. The solution that worked for me is to hold the actual instances of data singleton classes within an extension class of android.app.Application, whose lifecycle is well defined. Any other class that wants to access those singletons can obtain them using a getter in the Application class.
So for example I have a class called AppState that extends Application, that holds the instances within:
import android.app.Application;
public class AppState extends Application {
...
// "Singleton" instances that this Application extension looks after
private MSData singletonInstanceMSData;
public AppState() {
...
singletonInstanceMSData = new MSData();
...
// ---------------- Singleton instance control ----------------
public MSData getMSData(){
return singletonInstanceMSData;
}
// I also provide the means to 'reset' the instances on startup (this is
// something I need to do for my application - you may or may not need to)
public void resetControllerSpecificData(){
singletonInstanceMSData.reset();
...
Don't forget you'll need to modify your manifest if you extend Application.
AFAIR, lifespan os singleton is lifespan of his classloader - also complete VM . When user hit home button, your application goes in backgorund and is probably destroyed - you can not do anything against it. Your best bet is to save whatever is necessary in your onPause() callback ( or just use write through in every change of datza if you really paranoid )
I have a bug in my code that made me think I don't fully understand the Android Lifecycle. Yes, I have read all the docs and looked at the diagrams, but they seem to talk only about when to save data, when the activity may loose focus or get killed. However, my question is if I don't need to save state, what happens to the variables & their stored values? I expected them to be destroyed to, but a bug in my code seems to indicate otherwise.
In my case here is what happened. I have an activity that launches a custom view (no xml, I just draw bitmaps on the screen in my custom view). The only variable I currently have in my activity is just a variable for my view: GameView gameView;
Now in my view, I declare several bitmaps, simple int and float variable to deal with drawing and on touch events and I have one array of objects that contain small bitmaps, coordinates of each objects and a few other things. One of the variables in my class for this object, is a static variable that represents the current count of how many objects their are. I did it this way, so the instantiation of the objects causes it to track how man objects their are, instead of tracking this outside the object's class.
I expected the static variable to stay the same value across all objects, but I also expected this variable to be destroyed along with all the other variables and objects of that Activity's view once onDestroyed was called for that Activity. However, that doesn't seem to happen. When this Activity is launched again, this static variable still contains its previous value from its last run - even though onDestroyed was called.
Now my question is NOT how to fix this (I can write code differently to fix this bug), but I would like to understand why this happens with this static variable, since it isn't global to the whole application, it only exists inside that Activity's view? Also, this makes me wonder about the rest of the variables in that view - are they destroyed and their memory released or at least their values no longer available the next time the activity is called or do I need to do this myself - even though I didn't need to save any of this state data?
Thanks for any insight into this.
onDestroy is an instance method and any memory it releases (or allows the garbage collector to release) will be of the corresponding instance. Activities are not singleton; there can be more than one instance of an Activity.
Static variables are class variables and are accesible to all instances of that class. They are initialized when the class is loaded, not when each instance of the class is created.
Please see Understanding Instance and Class members for more info. An excerpt:
Sometimes, you want to have variables
that are common to all objects. This
is accomplished with the static
modifier. Fields that have the static
modifier in their declaration are
called static fields or class
variables. They are associated with
the class, rather than with any
object. Every instance of the class
shares a class variable, which is in
one fixed location in memory. Any
object can change the value of a class
variable, but class variables can also
be manipulated without creating an
instance of the class.