I have an application whose different activities need an access to many values that could be stored in a global variable in order to know which views should be visible and/or enabled. It is a kind of views-visibility variable. The thing is that I want to save all those visibility values in the different attributes of this object and I want this object to stay safety alive for all the application lifecycle, then is when I came down to global variables.
I've read different options to do this:
1) Creating this object in the main activity using Singleton pattern.
2) Creating this object as an static class and fulfilling the values in main activity.
3) Creating this object as a calss extending Application in the main activity.
Then the object is supposed to be called and accessed from each activity of the application. But, is any of these options correct and efficient to access global variables? Is it recommended to avoid using global variables?
Thank you
Related
I have an activity that consists mainly of a viewpager. The user can open new versions of that activity with different intents, thus making the data in the viewpagers different. Problem is when I access static variables in other classes from the main activity type, it seems as if it is editing variable values in all open versions of the activity. If I finish() the top activity,the data in the original activity has changed to that of the child activity. What is a way to keep references to static variables with only the current activity?
Thanks!
What is a way to keep references to static variables with only the current activity?
Quite simply - you can't.
In Java when you declare a variable as static in the main body of the class, it is a 'class variable'. This means that all instances of that class share only one variable between them. Consequentially (as you've already found out) changing the value in any instance of the class will change the value for all instances as there is only one 'copy' of the variable.
A golden rule in Android is to NEVER use static variables or methods in Activities.
There are two reasons for this - if your Activity is only ever extended within your ouwn code, then having a static variable or method is pointless and (as you've discovered), it's counter-productive.
The second reason is that static is often used with the public modifier in order to allow an 'all-areas' access to variables and/or methods regardless of whether an actual instance of any given class exists or not - in the case of the class being an Activity, this is a VERY dangerous game to play because of the life-cycle of Activities.
If you have a 'base' Activity which you want to start various instances of but want a common variable they all need to have access to, then simply declare it as...
protected Object myVariable;
...replacing Object with whatever type of variable you want.
Each Activity will get there own instance of myVariable and can change its value without affecting any other instance of the same Activity class.
See the following for Java Class Variables
I was wondering if I have 2 activities that needs to update and access the same object . What would be the best way to do it? Should I use Application class? Or perhaps Static variable.. Etc?
Another option I can think of is putting it in a base class that both activities inherit. I will initialize the object from shared preferences during OnResume
If your object holds some kind of preference value, don't put it into a super-class. Make it static and/or use the singleton pattern and separate it from your application logic. This provides you with a more modular structure that will be easier to work with. The application class is probably overkill; singletons do the job most of the time. (The Android docs simply states: "There is normally no need to subclass Application.")
You can add it to a super-class, if it is a logical part of it though.
Don't forget to synchronize your object if it's going to be accessed by another/several thread(s).
There are different method to perform such requirement. Singleton is one of them. The other one is extending the application class. If you want a reference outlining all of these methods please see:
What's the best way to share data between activities?
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).
Using itent.putExtra makes a copy of my object. So changes make on this object on the activity that recive this itent does no reflect on others activity.
In my case will be good have reference to this object instead a copy, this is possible ?
ps: I know i can use onActivityResult to retrive the changes make on the object, but in my case the changes make on the object need to be done before the end of the activity.
Other way is: set a reference to a common property from activity1 (I am using MyApplication). The activity2 knows where to find that reference via a getter and it will use it. Decide if you want to modify the properties in activity2, when finished / every time you can have the reference in activity1.
This way is not needed to serialize / deserialize the object either. ( performance improvement too)
You can just store a reference to the object in a static member variable, like this:
public class Globals {
public static MyObject myObject;
}
Now, in the code that has the object, you just do:
Globals.myObject = object;
and in the new activity, you can get it like this:
doSomethingWith(Globals.myObject);
Now, having said that, you need to be aware of the following:
Android can kill your process if your application is in the background pretty much any time it wants to. When the user then returns to your application, Android will create a new process for your application and then it will recreate only the activity that was on the top of the activity stack (ie: the one that was showing). In that case, the newly created activity will not be able to get the iobject by accesing Globals.myObject because the process has been newly created and that member variable is null.
You should use an Application class, which you can get a reference to using the getApplicationContext() method.
Bottom line, create an Application class, which you will be able to reference from any class in your App, then you can reference a variable that is local to that class.
Here is a good SO question about this:
Using the Android Application class to persist data
I have an application which has several screens. Lets say A B C D and D might open some external application as well.
All this activities share data, an arraylist with one another and I have created a reference to it in my Application class. (I have created a class which extends Application and referred to it manifest.) So all these are using single instance of arraylist. A initializes the arraylist since its first screen and others might modify it.
The problem is when I test this on emulator nothing gets broken. But on 'some' phones after 3+ screens of navigation arraylist just clears from the heap. No matter how small size is.
Use a singleton class for your ArrayList
Use singleton design pattern or make your object static
With the Singleton design pattern you can:
Ensure that only one instance of a class is created
Provide a global point of access to the object
Allow multiple instances in the future without affecting a singleton class's clients
Declare ArrayList as static in your first Activity then use it from any it will not broke up.