In an app there's always some data that needs to be used in multiple places. The data can be a session token, a time-consuming calculation, and so on. Typically, to avoid the overhead of passing objects between the activity, the data is generally stored in persistent storage .
It is suggested that this data be saved to the application object so that the data is available to all activities within the application. This method is simple, elegant and ... It's totally nonsense.
Assuming your data is stored in the Application object, your application will end up with a NullPointerException exception crash.
A simple test caseCode
Application object:
Access modifiers omitted for Brevityclass MyApplication extends application { String name; String GetName () { return name; } void SetName (String name) { this.name = name; }}
The first activity, we store the user name in the Application object:
Access modifiers omitted for Brevityclass whatisyournameactivity extends Activity { void onCreate (Bundle savedinst Ancestate) { super.oncreate (savedinstancestate); Setcontentview (r.layout.writing); Just assume in the real app we would really ask it! MyApplication app = (myapplication) getapplication (); App.setname ("Developer Phil"); StartActivity (New Intent (this, greetloudlyactivity.class)); } }
The second activity, we call the first activity setting and the user name inside the application:
Access modifiers omitted for Brevityclass greetloudlyactivity extends Activity { TextView TextView; void OnCreate (Bundle savedinstancestate) { super.oncreate (savedinstancestate); Setcontentview (r.layout.reading); TextView = (TextView) Findviewbyid (r.id.message); } void Onresume () { super.onresume (); MyApplication app = (myapplication) getapplication (); Textview.settext ("HELLO" + app.getname (). toUpperCase ());} }
Test Scenario
- The user launches the app.
- Inside the whatisyournameactivity , users are asked to enter their names and store them in MyApplication.
- In greetloudlyactivity , you get the user name from the MyApplication object and display it.
- The user presses the home key to leave the app.
- A few hours later, the Android system killed the app in order to reclaim memory. So far, everything is still fine. Next up is the crash part ...
- The user opens the app again.
- The Android system creates a new MyApplication instance and restores the greetloudlyactivity.
- greetloudlyactivity Gets the user's name from the new MyApplication instance, can be empty, and eventually leads to NullPointerException.
why would crash?
In the above example, the app will crash because the Application object is completely new, so the value inside the name variable is NULL, when the call to string#touppercase () Method results in NullPointerException.
The core of the whole problem is that the Application object will not stay in memory, it will be killed. What's different from the general view is that the app doesn't actually start again. The Android system creates a new Application object, and then initiates the activity from the last user's departure, causing the app to never be killed.
You think your application can save the data, but you didn't expect your users to open activity B without opening activity A, so you get a crash surprise.
What are the alternative methods?
There is no magic solution here, you can try the following methods:
- Pass data directly to the Activity via intent.
- Persist data to disk using several methods that are officially recommended .
- The value of the variable is always checked for non-null when working with the data.
- Local Data protection , in-depth protection of the APK app's network cache, local storage data.
If the simulation app is killed
Update: Daniel Lew points out that the easiest way to kill an app is to use the "stop process" inside DDMS. You can use this trick when debugging your app.
To test this, you have to use an Android emulator or a root Android phone.
- Use the home button to exit the app.
- In the terminal:
# Find the process idadb Shell ps# then find the line with the package name of your app # Mac/unix:save some time by usin G GREP:ADB Shell PS | grep Your.app.package # The result should look like:# USER PID PPID vsize RSS wchan PC name# u0_a198 21997 827940 22064 ffffffff 00000000 S your.app.package # Kill the app by pidadb Shell Kill-9 21997 # The app is now killed
- Press and hold the home button to return to the previous app.
You are now out of a new application instance.
Summary
Don't store data in application objects, which can be error-prone and cause your app to crash.
Either save the data you want to use behind the disk or save it to the intent extra and pass it directly to the activity.
These conclusions are not only useful for application objects, but also for the Singleton Objects (singleton) or public static variables in your app.
Why can't I store data in an Android Application object?