There are always some information, that's needed in many places in your app. It can be a session token, the result of an expensive computation, etc. It is often tempting to avoid the overhead of passing objects between activities or keeping those in persistent storage.
A pattern That's sometimes suggested is to dump your data in the Application object with the idea that it'll be availab Le across all activities. This solution are simple, elegant and ... totally wrong.
If you assume that your data would stay there, your application would eventually crash with a nullpointerexception.
A Simple Test casethe Code
The Application object:
1 2 3 4 5 6 7 8 910111213
|
//access modifiers omitted for Brevityclass myapplication extends application { string namestring getname () {return name void setname (string name {this.= name} /span> |
The first activity, where we store the name of the user in the Application object:
1 2 3 4 5 6 7 8 9101112131415
|
Access modifiers omitted for brevityClassWhatisyournameactivityExtendsActivity{voidOnCreate(BundleSavedinstancestate){Super.OnCreate(Savedinstancestate);Setcontentview(R.Layoutwriting//Just assume that in the real app we would really ask it! myapplication app = ( myapplication getapplication (); app. ( "Developer Phil" startactivity (new intent (thisgreetloudlyactivity.} /span> |
The second activity, where we shout the name of the user:
1 2 3 4 5 6 7 8 910111213141516171819
|
Access modifiers omitted for brevityClassGreetloudlyactivityExtendsActivity{TextViewTextView;voidOnCreate(BundleSavedinstancestate){Super.OnCreate(Savedinstancestate);Setcontentview(R.Layout.Reading);TextView=(TextView)Findviewbyid(R.Id.message void onresume () { super.myapplication app = ( Myapplication getapplication (); textview. ( "HELLO" + app. Getname (). } /span> |
The Scenario
- The user starts the app.
- In whatisyournameactivity, your ask for the name of the user and your store it in MyApplication.
- In greetloudlyactivity, you fetch the user's name from the MyApplication object and display it.
- The user leaves the app using the home button.
A few hours later, Android silently kills the app to reclaim some memory.
So far, so good!
But here comes the crashy part ...
- The user reopens the app.
- Android creates a new MyApplication instance and restores greetloudlyactivity.
- greetloudlyactivity Fetches the user ' s name, which is now null, and crashes with a nullpointerexception.
Why Does it Crash?
In this sample, we crash because the Application object are brand new, so the name variable are null, leading to a nullpoint Erexception when we call String#touppercase () on it.
Which brings us to the core of the Problem:the Application object would not be stay in memory forever, it'll get killed. Contrary to popular belief, the app won ' t is restarted from scratch. Android would create a new Application object and start the activity where the user is before to give the illusion that th E application is never killed in the first place.
Which means so if you expect some data to being in your application object just because your user was not supposed to be ABL E to open activity B before activity A, your is in for A crashy surprise.
What is the alternatives
There is no magic solution here, you can do one of the following:
- Explicitly pass the data to the Activity through the intent.
- Use one of the many ways to persist the data to disk.
- Always do a null-check and handle it manually.
How to simulate the application Being killed
Edit:as pointed out by Daniel Lew, an easier-to-kill your app is-to-simply use the ' Stop Process ' feature in DDMS. This would work on any phone as long as your application is debuggable.**
To test the must use an emulator or a rooted phone.
- Exit your app using the home button.
- In a terminal:
1 2 3 4 5 6 7 8 9101112131415
|
# Find the Process IDADB Shell PS # then find the line with the packagename of your app| grep your.app.package # The result should look like:# USER PID PPID vsize RSS wchan PC NAME# u0_a198 21997 827940 22064 ffffffff 000 00000 S your.app.packagekill-9 21997# The app is now killed |
- Now return to the app using the task switcher.
You is now on a new application instance.
The Bottom Line
Storing data in the Application object was error prone and can crash your app. Prefer storing your global data on disk if I T is really needed later or explicitly pass it to your activity in the intent ' s extras.
Also Remember that and this was true for the Application object, it was Also true for all singleton or public static field That you might has the in your app.
My final solution is to save it locally at SetName () and fetch it locally at getname ().
Don ' t Store Data in the application Object