When an application\'s process is killed, its activity stack is saved. Then when the application is restarted, all my activities resume and run into null pointers. Rather th
The solution above of relying on process death to reset a static variable works, but is a code smell due to it's reliance on static state. Here's a solution that has very similar properties, but doesn't rely on a static variable being reset after process death. Instead, it relies on the fact that after a process death any retained fragments will have their instance variables set back to default.
/**
* This retained fragment functions as a detector for when the activity is restoring it's state
* after a process death.
*
* The callback onRestoreInstanceState cannot be used here, since that callback is also invoked
* during regular activity recreation due to configuration changes, and there's no way to tell
* whether the state is being restored from a configuration change or from recreation after process
* death.
*
*
This retained fragment can be used to disambiguate these two scenarios. When the fragment is
* created, it's {@code wasProcessKilled} flag is set to {@code false}, which will be retained
* across activity restarts from configuration changes. However, on process rebirth, the retained
* fragment will still be retained, but the value of {@code wasProcessKilled} will be set back to
* its default value of {@code true}.
*/
public class ProcessDeathDetectorFragment extends Fragment {
public static final String TAG = "ProcessDeathDetectorFragmentTag";
public static ProcessDeathDetectorFragment create() {
ProcessDeathDetectorFragment frag = new ProcessDeathDetectorFragment();
frag.wasProcessKilled = false;
frag.setRetainInstance(true);
return frag;
}
private boolean wasProcessKilled = true;
public boolean wasProcessKilled() {
return wasProcessKilled;
}
@VisibleForTesting
public void clear() {
wasProcessKilled = true;
}
}
private void closeActivityIfRestoredAfterProcessDeath(Bundle bundle) {
FragmentManager fragmentManager = getSupportFragmentManager();
ProcessDeathDetectorFragment retainedFragment =
(ProcessDeathDetectorFragment)
fragmentManager.findFragmentByTag(ProcessDeathDetectorFragment.TAG);
if (bundle != null && retainedFragment != null && retainedFragment.wasProcessKilled()) {
// If the bundle is non-null, then this is a restore flow.
// If we are in a restore flow AND the retained fragment's wasProcessKilled flag is set back
// to its default value of true, then we are restoring
// from process death, otherwise the flag would have the value of false that was set when it
// was created for the first time.
finish();
return;
}
if (retainedFragment == null) {
fragmentManager
.beginTransaction()
.add(ProcessDeathDetectorFragment.create(), ProcessDeathDetectorFragment.TAG)
.commit();
}
}
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
closeActivityIfRestoredAfterProcessDeath(bundle);
...
}