suppose I have an activity, and it contains a TextView. I can initialize the TextView either to a member variable or to a local variable. is there any memory wise difference between these to initialization ?
example :
Activity with local view reference:
public class MainActivity extends Activity{
#OVerride
public void onCreate(Bundle b){
TextView textView = (TextView)findViewById(R.id.my_text_view_id);
}
}
Activity with member view reference:
public class MainActivity extends Activity{
TextView mTextView;
#OVerride
public void onCreate(Bundle b){
mTextView = (TextView)findViewById(R.id.my_text_view_id);
}
}
You should always use the minimal scope. So when you declare a variable you should ask yourself:
"Will I need this variable later in a different function?"
Yes -> Use a member variable
No -> Use a local variable
Edit:
What also to consider is the cost of object creation:
If a function does get called repeatedly it is a good practice to instanatiate an object only once, store it as a member variable and reuse it instead of creating a new instance every time the function gets called.
So the 2nd important question is:
"Will this function get called a lot and do I really need a new instance of the object stored in the variable?"
Yes, often, and no, I can reuse the same object over -> use a member variable. This way the same memory is used and no garbage gets piled up. Use only for large Arrays or objects, it is not needed for simple int vars in loops.
Memory wise global variables are much more prone to memory leaks. The scope any variable depends on its scope. For local variable, the scope is closing braces of the respected method, and variable is automatically garbage collected after the execution of closing braces. Where as global variable will reside in memory until the any object of that class is in memory.
Generally, try to avoid using 'global' variables unless you have good
reason to do .
You can use Local or Global Variable depends upon your Requirement .
Mainly, local variables are that they work within a limited scope means they are declared when a function is called and after ending it the memory taken up by the variable is released.
Finally usage of global variables leads to wastage of memory .
Related
I'm part of an Android project that uses a global class that contains public static variables, like the example below:
public class Globals {
public static MyObject variable = "this is a test";
}
In the middle of using the application, this global variable's value will be changed let's say:
#Override
public void onCreate(Bundle savedInstanceState) {
Globals.variable = new MyObject(somethingHere);
}
And I came across using Headless Retained Fragments from these blog posts:
http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html
http://www.vogella.com/tutorials/AndroidFragments/article.html#headlessfragments
Problem:
I need to have a reference of an initialized object all over the application.
Question:
which is better to implement, a good practice, and practical? Or is there another way I could store a reference of an object all over the application?
The global class has been used over the project, and works fine, but are there any downsides of this implementation?
are there any downsides of this implementation?
Memory leaks, depending on what you are storing there. Leaks are why static data members are considered poor form in classic Java, even if we tend to use them more in Android app development.
Also, this data needs to be considered a cache, one that has to be able to be lazy-created on first access. Your process can be terminated at any point (wiping out the static data member) and the user can return to any activity in your app (courtesy of the recent-tasks list). If you want this data to survive process termination, the most likely solution will be to persist it in a file, database, or SharedPreferences.
All that being said, a retained fragment is a per-activity solution, not a per-application solution, and so it is not a valid alternative for your scenario AFAICT.
I want to hold all my variables somewhere where every Activity can access them and modify them. I tried storing my variables in xml file but it only works one way, I can access them but not modify them. The other option that I have thought about is creating seperate helper class that holds all my variables and offers getValue(); and setValue(); methods, but problem with this is that I think it will be resetted every time I make object of this class. So Is there any other way to have storage for variables?
Your senod option is nearer.
In your Helper class just add a static variable
See:
Class MyHelper {
..
..
public static int globIntVar;
Where you want to use :
MyHelper.globIntVar = 2; // Setter
public int var = MyHelper.globIntVar; // Getter
You can use android.app.Application for Sharing data between diffrence components of Appliction. see this post:
Android: How to declare global variables?
Your requirement is to create some Global Variables, you can create some Global Variable by Using Application Class.
Check Example:
How to declare global variables in Android?
Make one class in your application which store all variables which are used through out application ex.
public Class Const{
Public static int siteurl="http://www.xyz.com/";
}
Now where ever you want to use that variable write
Const.siteurl
Is something wrong with this construct in Android?
class A extends Activity {
private Object myObject = new Object();
#Override
protected void onCreate(Bundle savedInstanceState) {
//myObject = new Object();
}
}
Because at some point(s) later I get (sometimes, not reproducible yet) exceptions because myObject is null. I don't know if it's because I have to initialize in onCreate.
Edit: Additional details:
The actual class of myObject is List<Object> (Where Object is a domain specific type)
At some point later in the activity I'm storing myObject as a static field of a "Parameter passer" class and starting other Activity (because I'm avoiding to implement Parcelable. If this is good or bad practice should not be discussed here, unless that's causing my error). In the other Activity I pick up myObject. There it's (sometimes) null.
Edit 2: I don't understand why this object becomes null if I'm storing a reference to it as static field of my parameter passer class (a standalone, dedicated class). That's how garbage collection works, right, it just removes when the objects are not referenced anymore. So since I have a static reference this object should not be removed. According to this thoughts, if they are correct, the problem should be somewhere else.
When you start a new activity your old one goes on the block for possible garbage collection (including any classes instantiated in it, including your parameter passer class), so your object is not necessarily going to be available (which is why you see an intermittent failure.).
I see two option:
1) Pass it along in the bundle with your intent that starts the new activity. As you were trying to avoid this, probably not your best choice.
2) Extend the Application class and store the object in there.
EDIT
I think the accepted answer to this SO Question might fix your issue (and explain what is actually happening).
No. That code is just fine. You can create objects in the constructor.
You may want to check a previous question about it Instance variable initialization in java and the section 3.2.4. Field Defaults and Initializers which basically states that the first case:
private Object myObject = new Object();
is identical to an initialization in the class constructor. (NOTICE onCreate is NOT the constructor).
So, myObject should never be null, except in the case the "new Object()" instruction failed, generating an exception.
Isn't this possible your code is changing the contents of myObject later on the code?
I'm developing an app that has a DataManager class, which holds an ArrayList<Object[]>. As this ArrayList needs to be used within other classes, I am wondering what would be the most efficient and fastest way of accessing this list, considering this application will be running on the Android platform.
A) create a public static ArrayList<Object[]> data in the DataManager class and reference it within other classes through DataManager.data
B) create a public ArrayList<Object[]> getData method within the DataManager class and have methods within other classes create local variable ArrayList<Object[]> data = mDataManager.getData() for temporary use.
C) ..?
It seems to me B has more overhead due to object creation. Also I read static is faster than non-static?
Option B does not increase memory use, since you will only have one ArrayList object (all the objects that use it just hold a simple reference, not a copy). The objects that use the ArrayList could also store this reference as an instance variable, instead of requesting it from the manager class each time it is needed.
I read somewhere that access to instance variables is slightly faster than accessing class (static) variables, but I don't have the link to the source.
The difference in performance is not likely to be meaningful. However, Option B gives you better encapsulation.
When I'm writing a method or using a member variable, I often find I need to share them across an app. But where should they go?
I can subclass Activity, but that falls over as soon as I use a MapView and am forced to use MapActivity, so not all my activities inherit from my subclass. Is there I way around this?
Where inheritance isn't applicable, I am tending to put generic methods and member variables into a subclass of the Application object, but I'm finding it's creating a mess of code as every class needs to either grab access to the application object through via context, or I have to pass it down.
I suspect I would be better off creating MyApplication.getInstance() and keeping everything in a singleton, instead of passing the application object down through the app classes. but before I wanted to see what you guys had to say.
If you want to access the "Global Singleton" outside of an activity and you don't want to pass the Context through all the involved objects to obtain the singleton, you can just define, as you described, a static attribute in your application class, which holds the reference to itself. Just initialize the attribute in the onCreate() method.
For example:
public class ApplicationController extends Application {
private static ApplicationController _appCtrl;
public static ApplicationController getAppCtrl()
{
return _appCtrl;
}
}
One example with resources: Because subclasses of Application also can obtain the Resources, you could access them simply when you define a static method, which returns them, like:
public static Resources getAppResources()
{
return _appCtrl.getResources();
}
For global methods, use a static Util class with static methods. If you can't use static methods, then the methods shouldn't be global in the first place, and put them in the class that makes sense.
First read this:
How to declare global variables in Android?
Now why you shouldn't use a static singleton. Using a singleton is a the same thing as a global variable. Global variables reduce your maintainability because everywhere you use the global variable you break modularity or introduce global details and assumptions about your overall design. Your program can't have two of these variables because it only looks in one place for it. This means your program can't adapt easily when you have two instances instead of one.
For example, say I have a method called playTurn() and I implement it like so:
public void playTurn() {
globalPlayer.incrementClock();
globalPlayer.doSomething();
globalPlayer.doSomethingElse();
}
Now let's say I want to add a second player to the mix. Uh oh my playTurn() method assumes one player only when it used globalPlayer. If I want to add a second player to the program I have to change that method. Do this a lot and your program is very rigid and inflexible to change. Instead what if I did this:
public void playTurn(Player player) {
player.incrementClock();
player.doSomething();
player.doSomethingElse();
}
Now can do this:
playTurn( player1 );
playTurn( player2 );
I can reuse playTurn() for both player1 and player2 and I didn't have to change it. I just had to change the client of that method.
Most of the time you're being lazy and you want to get a reference to some object, and global variables are fast ways to get references to well known objects. Instead it's better to have one class that resolves the dependencies across your application at start up or the time when it makes sense. Then only that one place understands how your code is put together. For example,
public class Game {
Player player1;
Player player2;
Board board;
public void startGame() {
BlueTooth blueTooth = BlueTooth.getChannel();
player1 = new LocalPlayer();
player2 = new NetworkedPlayer( blueTooth );
board = new Board();
player1.setOpponent( player2 );
player1.setBoard( board );
player2.setOpponent( player1 );
player2.setBoard( board );
}
}
Now everyone has their dependencies, and they don't need to use static variables to find references to things. Also player1 doesn't have to know about details like that player2 is over the network, or that it's apart of a Game. What's important to note is that these objects we're connecting have a long life, possibly the entire program, but if they need to create other things at runtime that's ok for them to do.
Say for example, we need to create multiple players at runtime based on who joins the game. Well we might create a PlayerManager that we can instantiate at startup then create Player objects on the fly. PlayerManager is just a plain old object that we create in Game when we start a new game.
I hope you can start seeing this is a much better way to develop software. You might not understand it right off, but if you think about it will make more sense. It's very subtle change, but very powerful.