As an alternative to an Intent
, i'm saving data in a retained headless Fragment
during Activity
re-creation (my saved object can be pretty large and it wouldn't fit the size limit of an Intent
, and i think this is a faster approach than serializing-deserializing into JSON for example).
I've got the idea from this Google documentation, although my implementation is a bit different.
The Fragment
:
public class DataFragment extends Fragment {
private Data data;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
public void setData(Data data) {
this.data = data;
}
public Data getData() {
return data;
}
}
I save my data to this Fragment
in the onSaveInstanceState()
method of my Activity
:
@Override
protected void onSaveInstanceState(Bundle outState) {
FragmentManager fm = getSupportFragmentManager();
dataFragment = (DataFragment) fm.findFragmentByTag(TAG_DATA);
if (dataFragment == null) {
dataFragment = new DataFragment();
fm.beginTransaction().add(dataFragment, TAG_DATA).commitNow();
}
dataFragment.setData(myData);
super.onSaveInstanceState(outState);
}
And the relevant part of onCreate()
:
Data data;
FragmentManager fm = getSupportFragmentManager();
dataFragment = (DataFragment) fm.findFragmentByTag(TAG_DATA);
if (dataFragment == null) {
// the Fragment is not attached, fetching data from DB
DatabaseManager dbm = DatabaseManager.getInstance(this);
data = dbm.getData();
} else {
// the Fragment is attached, fetching the data from it
data = dataFragment.getData();
fm.beginTransaction().remove(dataFragment).commitNow();
}
This works flawlessly on orientation changes.
The problem is, sometimes, when my app is in the background and i'm returning to it, dataFragment.getData()
returns null
.
In other words, in the following line in onCreate()
sometimes data
is null
:
data = dataFragment.getData();
How is this possible?
It does not throw a NullPointerException
, so dataFragment
is not null
for sure.
Why did its initialized instance variable became null
?
What you experience is PROCESS DEATH.
Technically it's also called "low memory condition".
The retained fragment is killed along with the application, but the FragmentActivity recreates your retained fragment in super.onCreate()
, so you'll find it by its tag but the data in it won't be initialized.
Put the app in background then press the red X in the bottom left in Android Studio to kill the process. That recreates this phenomenon.
NOTE: After AS 4.0, if you launch your app from AS, then "Terminate" will trigger Force Stop (which does not produce this phenomenon). But if you launch your app from LAUNCHER on the phone after that, then you'll get this phenomenon.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With