I got a TransactionTooLargeException
. Not reproducible. In the docs it says
The Binder transaction failed because it was too large.
D
This exception is typically thrown when the app is being sent to the background.
So I've decided to use the data Fragment method to completely circumvent the onSavedInstanceStae
lifecycle. My solution also handles complex instance states and frees memory ASAP.
First I've created a simple Fargment to store the data:
package info.peakapps.peaksdk.logic;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
/**
* A neat trick to avoid TransactionTooLargeException while saving our instance state
*/
public class SavedInstanceFragment extends Fragment {
private static final String TAG = "SavedInstanceFragment";
private Bundle mInstanceBundle = null;
public SavedInstanceFragment() { // This will only be called once be cause of setRetainInstance()
super();
setRetainInstance( true );
}
public SavedInstanceFragment pushData( Bundle instanceState )
{
if ( this.mInstanceBundle == null ) {
this.mInstanceBundle = instanceState;
}
else
{
this.mInstanceBundle.putAll( instanceState );
}
return this;
}
public Bundle popData()
{
Bundle out = this.mInstanceBundle;
this.mInstanceBundle = null;
return out;
}
public static final SavedInstanceFragment getInstance(FragmentManager fragmentManager )
{
SavedInstanceFragment out = (SavedInstanceFragment) fragmentManager.findFragmentByTag( TAG );
if ( out == null )
{
out = new SavedInstanceFragment();
fragmentManager.beginTransaction().add( out, TAG ).commit();
}
return out;
}
}
Then on my main Activity I circumvent the saved instance cycle completely, and defer the respoinsibilty to my data Fragment. No need to use this on the Fragments themselves, sice their state is added to the Activity's state automatically):
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
SavedInstanceFragment.getInstance( getFragmentManager() ).pushData( (Bundle) outState.clone() );
outState.clear(); // We don't want a TransactionTooLargeException, so we handle things via the SavedInstanceFragment
}
What's left is simply to pop the saved instance:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(SavedInstanceFragment.getInstance(getFragmentManager()).popData());
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState( SavedInstanceFragment.getInstance( getFragmentManager() ).popData() );
}
Full details: http://www.devsbedevin.net/avoiding-transactiontoolargeexception-on-android-nougat-and-up/