What to do on TransactionTooLargeException

前端 未结 30 3346
盖世英雄少女心
盖世英雄少女心 2020-11-22 03:08

I got a TransactionTooLargeException. Not reproducible. In the docs it says

The Binder transaction failed because it was too large.

D

30条回答
  •  醉话见心
    2020-11-22 03:36

    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/

提交回复
热议问题