android static variable behaviour on application crash - android

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.

Related

Does android save static variables?

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).

Using Activity class static members in a background service

My app has an Activity class called MainActivity and one of its members is
public static SharedPreferences prefsdefault;
My app has also a service (in another process) which runs in background. Inside the service I wrote
MainActivity.prefsdefault.getString(Key,"Hello");
The app sometimes throws null pointer exception at this line. Why? Does it mean that this member is cleaned up by the garbage collector when I close the activity and I cannot access it at anytime (when my service runs)? So what is the perfect solution for this?
Should I pass the MainActiviy.class to the service? It also happens when I implement a thread that requires a context.
That's because, even if your prefsdefault may have been initialized once, your whole app can be garbage collected and restarted again.
In that case your service will find that field as null. Using static fields inside activities is wrong for a bunch of reasons, the most important is that your app may be killed and restarted by the operating system and after that all the static fields are wiped out again.
The correct way to use shared preferences is to access them using getSharedPreferences whenever you need to access / write.
The other weird thing is that you say that the service runs in another process. In that case it should not be able to access to data from another process.
Because prefsdefault is NULL. I don't see that it is initialized.
You can do that by
prefsdefault = getSharedPreferences("my_preferences", Activity.MODE_PRIVATE);
Hot tip: Never make your SharedPreference instance static.
The reason for this is SharedPreferences is not initialised u dont need to do like this as SharedPreferences are global available with in app if MODE is Private just create new instance in service as well it will work

State of variables inside an Android activity

I have defined a global variable inside an activity, this variable changes depending on the button user has pressed.
If I go outside of my app UI and come back by holding the home button which shows the list of recent apps, then my variable keeps its state, but if I run my app again by pressing the app aicon the variable state is gone.
Is there a way to keep the state of the variable?
You can save the variable's value during the onSaveInstanceState() callback. Then you use the "icicle" parameter that is passed to and onCreate() to restore the value. You might be interested in reading Managing the Activity Lifecycle.
Also note that Java has class variables and member variables but not global variables.
As what #Code-Guru says, you could use onSaveInstanceState() to save variable's value.
Another simple way to do is to create a static member in a static class to store the variable. The static class exists as long as the app is in the memory.
You can consider to use shared preferences This class is used to store and retrieve simple data.

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.

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.

Categories

Resources