Does android save static variables? - android

I'm writing a simple android application which is basically a modification of the fragments demo available in the android documentation.
In the app, there is a file called Ipsum.java which has a static ArrayList of Strings called Headlines.
In the onCreate() method of the main activity, I have the following code which adds some elements into the array list.
if (savedInstanceState == null){
Ipsum.Headlines.add("String 1 ");
Ipsum.Headlines.add("String 2");
}
savedInstanceState is a Bundle that the system passes to the method, if the app is being resumed from some inactive state. The logic is that if savedInstanceState is null, then the app is not being resumed but being started as a new instance.
If I leave the app using the "Home" button and re-enter the app, the arrayList contains only the two elements: "String 1" and "String 2". (This is the desired behavior)
However, if I leave the app using the back button, and then re-enter the app, the "String 1" and "String 2" elements are added again. The array then has 4 elements.
String 1
String 2
String 1
String 2
(The contents of the arrayList can be seen because they are used to populate a listView)
It seems that the app is storing the contents of the static array list when the back button is pressed.. and that a Bundle is not passed to the onCreate() method when the app is restarted. Can someone explain what's happening here, in terms of the app life cycle?

May This Help you:
Lets start with a bit of background: What happens when you start an application?
The OS starts a process and assigns it a unique process id and allocates a process table.A process start an instance of DVM(Dalvik VM); Each application runs inside a DVM.
A DVM manages class loading unloading, instance lifecycle, GC etc.
Lifetime of a static variable: A static variable comes into existence when a class is loaded by the JVM and dies when the class is unloaded.
So if you create an android application and initialize a static variable, it will remain in the JVM until one of the following happens:
1. the class is unloaded
2. the JVM shuts down
3. the process dies
Note that the value of the static variable will persist when you switch to a different activity of another application and none of the above three happens. Should any of the above three happen the static will lose its value.
For More Detail: Read the Answer of Samuh in this Link... Click Here

Your activity is being resumed. If you want to control what happens, implement onResume().
See Managing the Activity Lifecycle for details.
EDIT:
Static variables are a Java concept. static just means that there is only one copy of the variable for the whole class. The alternative is that each object would have it's own copy.
So while your code is running, you just have one copy of the variable in your program. It doesn't get saved anyplace, unless you add code to do that.

Static variables are associated with a class and they will live as long as the class is in the memory,and destroy when class gets unloaded (which very rarely happens). It can happen when-
-You force stop your app.
-Application crashes.
-You clear your app data.
-Switch off your Device(Shutdown DVM).

Related

Different objects

In an app I'm making I have an Object to a class called Preferences in my MainMenu activity. I want to use this object in several pages. In the object is a class which contains an array with numbers. When I use it in another activity (Film) it changes one of the numbers in the object. Then I go back to the main menu and into a new activity (CurrentPrefs) in which I display the array of numbers on the screen. When I displayed the numbers they didn't contain the changes made in the Film file. So I started testing around with the variables a bit.
When I start the MainMenu, which is the start activity, it sets the object. Then when I enter film and check the object it still has the same name (object.toString()). I also checked to make sure that the values where changed correctly which they were.
Next I went back to MainMenu and checked again. The object still had the same name and the value were also like I changed them in Film.
Finally I entered the CurrentPrefs activity and there it goes wrong. The object suddenly has a different name and it also no longer contains the changes I made to it.
Why has the object changed and, more importantly, how can I make sure it doesn't change and stays the same everywhere?
There are any number of reasons why your object's values changed. Perhaps the previous Activity got destroyed and recreated without you realizing it.
You should check out Android's SharedPreference class. It is a way to store, edit, and retrieve preferences and have access to them in any Activity:
http://developer.android.com/reference/android/content/SharedPreferences.html
If you well know activity's lifecycle you can also understand why it happens. Probably some of your operation are delegated to onResume() method which is called whenever activity comes back from onPause() or immediately after onCreate(), while other operations reside in onCreate() called only when activity starts or after onDestroy(). I advise you to control this and trying to move all setText() in onResume() so that every updated object's variable will be read again.

Storing Data on Non-Activity classes

I would like to determine if this is bad practice, since I have implemented this in some locations.
I have two activities, MainActivity and SecondActivity.
If I want to transfer the string "Hello" from Main to Second, I use a class called Transfer. In this class I have a static String that I set to "Hello", which I access from the onResume method of SecondActivity.
How does android manage the "Transfer" class? Is it tied to MainActivity and destroyed along with it? Is there any other behavior I should be aware of?
Given that the String field is static, I'd say is bounded to the whole process and not to the MainActivity.
The problem is, the android os might free your app's resources to start another process.
What may happen is that your app gets backgrounded, the os needs it resources and frees the memory, and then the user gets back to SecondActivity. The process gets recreated and the previously initialized static field is now null.
If your need is to pass Strings between activities, I would bundle them into the intent's extras.
Static members exist as long as the app is in the memory.
This approach works fine. Another way to share data between two activities is to make use of putExtra to put data into second activity and getExtras to get the data.

android static variable behaviour on application crash

In my application I have Loginactivity. It has a static variable username and it will be assigned with the user enter values of username. Loginactivity launch activity A and A launch B. In A i use the variable Loginactivity.username.
Now due to some bug in B, application crashes. When I press force close, application is restarted and activity A is the current activity. In activity A I am using a static variable Loginactivity.username. I see that after crash this variable is getting its initial value which is empty string "";
Why is it happening like this? Can you explain this behaviour? So when application crashes all the activities in the stack are restarted? I see that oncreate of Loginactivity is not getting called. Then how is the static variable value getting changed ?
Yes, when an application crashes, the jvm for this app is restarted, your classes are reloaded and you lose all static variables as well as instance variables.
The solution is to remove the crash cause. :)
Use SharedPreferences instead, or store information in Application class
When your Activity B crashes the Android Dalvik Virtual Machine that your application runs in (each app has its own DVM which are separate processes) is killed. When you are starting Activity A the username is "" because Java by defaults sets all instance variable (class variable or fields if you like) to null (references), 0 (primitives), and "" for strings. So your Activity A is working correctly. You just need to either store the username in the shared preferences, a database, or trigger the event for the user to login again... I would also fix Activity B... Haha
This is because you have a memory leak caused by this static member you keep in LoginActivity.
I would consider keeping this variable in Application scope (custom application class) or save it into DB.
Anyway, just remember to nullify this variable when your application is done.

Could the values on global variables have been reset when an Android app resumes?

When an app have been put into the background and later resumes to an activity, is it possible that static class variables set in another Activity could have been reset by the garbage collector and have got the value set to zero?
I use a couple of public static int variables in my main Activity and use them as global variables in various other Activities. I have received a crash report in the developer console from Android Market where the only explanation I can find is that the app resumes to an Activity which uses the value of a public static int variable in another class, but the value has (mysteriously?) become zero. I know that it was set to something else when the app first started. Is this at all possible?
If my suspicion is correct, what is the recommended way to preserve the values of the global variables when an app is put in to background? Save them in SharedPreferences in OnPause() or use onSaveInstanceState or something else?
When an app have been put into the background and later resumes to an activity, is it possible that static class variables set in another Activity could have been reset by the garbage collector and have got the value set to zero?
It would not be "reset by the garbage collector". However, the process may have been terminated by Android, to free up memory for other applications.
what is the recommended way to preserve the values of the global variables when an app is put in to background?
Static data members should only be a cache. Data you want to retain regardless of what happens (e.g., process being terminated) needs to go in some persistent store, such as a flat file, SharedPreferences, or database. onPause() is a likely time to arrange to persist that data, as any time after that, your process could be terminated without notice.
Be careful with static variables. Follow the link for an explanation concerning Singleton (which also use a static variable to maintain state): https://stackoverflow.com/a/9004638/1127492
You can save this values on SQLite on method onDestroy in activity or another method with response to exit.

Is static variable really safe to exchange data between activities?

I'm working on an application that consist of a couple of activities:
Activity 1: main screen of an application with a "Start" button
Activity 2: user selects its identity from the list (more than one user is going to use the application)
Activity 3: user inputs password
Activity 4: user chooses an event from a timetable (every user has its own timetable with associated events)
Activity 5: user can choose an action connected with an activity.
Activities 6-10: user performs appropriate action.
Below some more information:
every activity from 6-10 have to know what user is logged in and what event has been selected
every activity from 6-10 has a menu that allows the user to go back to activities: 1 (to log out), 4 (to select different event), 5 (to select different action)
Since now, I've been using bundles to exchange data between activities but it seems to complicate the code as the number of actions grow (some actions use a 3-4 activities to collect data from the user). Passing all the data to every created activity doesn't seems to be nice.
I'm thinking about storing the "user name" and selected "event" as a static fields of a class. I will simplify the code very much, but I'm not sure whether this data will persist if the user let say at some point press "home button" and run another application that needs a lot of memory.
Will the data stored in static fields be safe?
It's better to have a custom Application object and store them there. The application object will live aslong as your app does.
http://developer.android.com/reference/android/app/Application.html
You can get access to the Application object by casting getApplicationContext() to whatever your custom Application type is:
public class CustomApplication extends Application {
private String userId;
public void onCreate() {
super.onCreate();
...
}
public String getUserId() {
return userId;
}
...
}
From Activity call: ((CustomApplication) getApplicationContext()).getUserId();
No. You are not guaranteed that these will all exist in the same classloader, in which case you would be dealing with different copies of these classes in different places, and not accessing the same shared state.
It may happen to work now; but no it is not something I would call "safe".
you can use the SharedPreference for this instead of using static variable/object into the class. check out this blog http://android-er.blogspot.com/2011/01/example-of-using-sharedpreferencesedito.html
You should just use the intent system as designed. Statics and Activities can get killed seemingly willy-nilly by Android. Even the Application class can get killed.
Say your have an app consisting of two activities, the first one lets the user store some data in the Application object. The user then clicks a button to start the second activity which displays the data. The user puts their phone down and comes back to it several hours later.
Android might decide to kill the app for various reasons during this time. When the user comes back, picks up the phone and relaunches your app a new Application object will be created and the second activity will be restored but the data the user entered will no longer be available in the Application object because it is a new Application object.
One way to help with this is to use SharedPreferences even for complex objects. Gson is perfectly capable of serializing and deserializing them to SharedPreferences.
To simulate this you can do the following:
$adb shell ps | grep your.app.package
to get the pid of your running app, then
$ adb shell kill -9
then open the app with the task switcher and you will have a new Application object but will be on the second activity.
Static fields work but not graceful. You just need a session object following singleton pattern.
Static data will persist on pressing home button and on opening your application again you will go to the same state where you left but when you run another application which needs lot of memory there are possibilities that you may lost your all static data.
But if you have very less static data then it may persist.
You can also look for SharedPreference.
You can Use the static unless and untill you are sure that this static variable will not conflict the users.
also static variable are class's property so it consumes more memory because lifetime is application level.
other i can suggest is to use shared prefereces which very handy. this shared preferences can be access by any of the activity of your application. so no need to pass bundle and worry about static fields.
last option is which is i dont find importance in your application is "Use Database to store and retreive".
Hope this helps.

Categories

Resources