Android.os.TransactionTooLargeException on Nougat

I upgraded the Nexus 5X to Android N, and now when I install the application (debug or release), I get a TransactionTooLargeException on every screen that has a Bundle in additional applications. The application works on all other devices. The old application, which is located on the PlayStore and has basically the same code, works with the Nexus 5X. Does anyone have the same problem?

java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 592196 bytes at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3752) at android.os.Handler.handleCallback(Handler.java:751) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6077) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755) Caused by: android.os.TransactionTooLargeException: data parcel size 592196 bytes at android.os.BinderProxy.transactNative(Native Method) at android.os.BinderProxy.transact(Binder.java:615) at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3606) at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3744) at android.os.Handler.handleCallback(Handler.java:751) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6077) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755) 
+69
android android-7.0-nougat
Aug 23 '16 at 10:25
source share
13 answers

In the end, my problem was the things that were stored in SaveInstance, and not the things that were sent to the next activity. I deleted all the sevs where I can not control the size of the objects (network responses), and now it works.

Update:

To save large chunks of data, Google suggests doing this with a fragment that saves the instance. The idea is to create an empty fragment without a view with all the necessary fields that would otherwise be stored in the Bundle. Add setRetainInstance(true); into the onCreate fragment method. And then save the data in Fragment on Activity onDestroy and load it onCreate. Here is an example Activity:

 public class MyActivity extends Activity { private DataFragment dataFragment; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // find the retained fragment on activity restarts FragmentManager fm = getFragmentManager(); dataFragment = (DataFragment) fm.findFragmentByTag("data"); // create the fragment and data the first time if (dataFragment == null) { // add the fragment dataFragment = new DataFragment(); fm.beginTransaction().add(dataFragment, "data").commit(); // load the data from the web dataFragment.setData(loadMyData()); } // the data is available in dataFragment.getData() ... } @Override public void onDestroy() { super.onDestroy(); // store the data in the fragment dataFragment.setData(collectMyLoadedData()); } } 

And an example snippet:

 public class DataFragment extends Fragment { // data object we want to retain private MyDataObject data; // this method is only called once for this fragment @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // retain this fragment setRetainInstance(true); } public void setData(MyDataObject data) { this.data = data; } public MyDataObject getData() { return data; } } 

You can read more about this here .

+25
Sep 28 '16 at 12:10
source share

Whenever you see that a TransactionTooLargeException occurs when an Activity is in the process of being stopped, it means that the Activity tried to send the saved state of the Bundles to the system OS to save safely for recovery later (after a configuration change or process death), but one or more The sent Bundles were too big. The maximum limit of about 1 MB for all such transactions occurs immediately, and this limit can be reached even if no Bundle exceeds this limit.

The main reason here is to save too much data inside the onSaveInstanceState either an Activity or any Fragments hosted by an Activity . This usually happens when you save something of a particularly large Bitmap type, but it can also occur when sending large amounts of smaller data, such as lists of Parcelable objects. The Android team has repeatedly stated that onSavedInstanceState should only save small data related to viewing. However, developers often kept pages of network data so that configuration changes appeared as smooth as possible, since they did not have to retrieve the same data. Starting with Google I / O 2017, the Android team has clearly indicated that the preferred Android app architecture preserves network data.

  • in memory, so it can be easily reused when changing the configuration.
  • to disk so that it can be easily restored after the process and application sessions are completed.

Their new ViewModel framework and Room conservation library are designed to help developers match this pattern. If your problem is storing too much data in onSaveInstanceState , updating this architecture used by these tools should fix your problem.

Personally, before upgrading to this new template, I would like to use my existing applications and just get around TransactionTooLargeException in the meantime. I wrote a quick library to do just that: https://github.com/livefront/bridge . It uses the same general ideas about restoring a state from memory when a configuration is changed and from disk after a process dies, and does not transfer all this OS state through onSaveInstanceState , but requires very minimal changes in your existing code to use. Any strategy that meets these two goals should help you avoid exclusion, but without sacrificing your ability to maintain state.

In conclusion, we note: the only reason you see this in Nougat + is that initially, if the binder’s forwarding limit has been exceeded, the process of sending the saved state to the OS will fail, only this error appears in Logcat:

!!! INCORRECT DEAL DEAL !!!

In Nougat, this silent failure was raised to a severe accident. To their credit, this is what the development team documented in the release notes for Nougat :

Now many platform APIs have begun to verify that large transactions are passed through Binder transactions, and now the system updates TransactionTooLargeExceptions as RuntimeExceptions, rather than silently registering or suppressing them. One common example is storing too much data in Activity.onSaveInstanceState (), which causes ActivityThread.StopInfo to throw a RuntimeException when your application targets Android 7.0.

+25
Jun 24 '17 at 16:14
source share

TransactionTooLargeException has been haunting us for about 4 months and we finally resolved the problem!

What happens, we used the FragmentStatePagerAdapter in the ViewPager. The user will browse the pages and create more than 100 fragments (reader application).

Although we manage fragments correctly in destroyItem (), an error appears in androids when implementing FragmentStatePagerAdapter, which contains a link to the following list:

 private ArrayList<Fragment.SavedState> mSavedState = new ArrayList<Fragment.SavedState>(); 

And when Android FragmentStatePagerAdapter tries to save the state, it will call a function

 @Override public Parcelable saveState() { Bundle state = null; if (mSavedState.size() > 0) { state = new Bundle(); Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()]; mSavedState.toArray(fss); state.putParcelableArray("states", fss); } for (int i=0; i<mFragments.size(); i++) { Fragment f = mFragments.get(i); if (f != null && f.isAdded()) { if (state == null) { state = new Bundle(); } String key = "f" + i; mFragmentManager.putFragment(state, key, f); } } return state; } 

As you can see, even if you correctly manage the fragments in the subclass of FragmentStatePagerAdapter, the base class will still store Fragment.SavedState for each individual fragment ever created. TransactionTooLargeException will occur when this array is discarded in parcelableArray and the OS does not like more than 100 elements.

Therefore, the fix for us was to override the saveState () method and not store anything for the "states".

 @Override public Parcelable saveState() { Bundle bundle = (Bundle) super.saveState(); bundle.putParcelableArray("states", null); // Never maintain any states from the base class, just null it out return bundle; } 
+17
Apr 03 '17 at 20:14
source share

There was a hit and a test, and finally it solved my problem. Add this to your Activity

 @Override protected void onSaveInstanceState(Bundle oldInstanceState) { super.onSaveInstanceState(oldInstanceState); oldInstanceState.clear(); } 
+14
Sep 23 '17 at 6:39 on
source share

I am facing this issue also on my Nougat devices. My application uses a snippet with a view pager that contains 4 snippets. I passed a few big construction arguments to the 4 fragments that caused the problem.

I traced the size of the Bundle calling this using TooLargeTool .

Finally, I solved this using putSerializable for a POJO object that implements Serializable instead of passing a large raw String using putString during fragment initialization. This halves the size of the Bundle and does not raise a TransactionTooLargeException . Therefore, please make sure that you do not pass huge arguments to Fragment .

Problem with PS in Google's Problem Tracking System: https://issuetracker.google.com/issues/37103380

+9
Jun 14 '17 at 8:36 on
source share

I am facing a similar problem. The problem and scenario are slightly different, and I fix it as follows. Check out the scenario and solution.

Scenario: I had a strange error with a client in a Google Nexus 6P device (7 OS), since my application will crash after 4 hours of operation. Later, I discovered that it was throwing a similar (android.os.TransactionTooLargeException :) exception.

Solution: The magazine did not indicate any specific class in the application, and later I discovered that this was due to the preservation of the back stop of the fragments. In my case, four fragments are added to the back stack several times using motion animation with an automatic screen. Therefore, I override onBackstackChanged (), as mentioned below.

  @Override public void onBackStackChanged() { try { int count = mFragmentMngr.getBackStackEntryCount(); if (count > 0) { if (count > 30) { mFragmentMngr.popBackStack(1, FragmentManager.POP_BACK_STACK_INCLUSIVE); count = mFragmentMngr.getBackStackEntryCount(); } FragmentManager.BackStackEntry entry = mFragmentMngr.getBackStackEntryAt(count - 1); mCurrentlyLoadedFragment = Integer.parseInt(entry.getName()); } } catch (Exception e) { e.printStackTrace(); } } 

If the stack exceeds the limit, it will automatically go to the original fragment. I hope someone helps with this answer because the exception tracking and stack logs are the same. Therefore, whenever this problem occurs, check the back stack counter if you are using fragments and a back stack.

+8
Dec 23 '16 at 11:27
source share

In my case, I got this exception inside the fragment because one of its arguments was a very large line that I forgot to delete (I used only this large line inside the onViewCreated () method). So, to solve this, I just deleted this argument. In your case, you must clear or invalidate any suspicious field before calling onPause ().

Activity code

 Fragment fragment = new Fragment(); Bundle args = new Bundle(); args.putString("extremely large string", data.getValue()); fragment.setArguments(args); 

Fragment Code

 @Override public void onViewCreated(View view, Bundle savedInstanceState) { String largeString = arguments.get("extremely large string"); //Do Something with the large string arguments.clear() //I forgot to execute this } 
+5
Apr 02 '18 at 5:57
source share

The problem in my application was that I tried to save too much on saveInstanceState, the solution was to determine exactly what data should be saved at the right time. Basically, take a close look at your onSaveInstanceState to make sure you are not stretching it:

 @Override public void onSaveInstanceState(Bundle savedInstanceState) { // Save the user current state // Check carefully what you're adding into the savedInstanceState before saving it super.onSaveInstanceState(savedInstanceState); } 
+2
Mar 10 '17 at 14:38
source share

Just override this method in your activity:

 @Override protected void onSaveInstanceState(Bundle outState) { // below line to be commented to prevent crash on nougat. // http://blog.sqisland.com/2016/09/transactiontoolargeexception-crashes-nougat.html // //super.onSaveInstanceState(outState); } 

For more information, go to https://code.google.com/p/android/issues/detail?id=212316#makechanges .

+1
Dec 13 '16 at 13:53 on
source share

I ran into the same problem. My workaround disables saveInstanceState for files in the dir directory.

I made the following utility class.

 package net.cattaka.android.snippets.issue; import android.content.Context; import android.content.SharedPreferences; import android.os.Build; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; /** * To parry BUG of Android N. https://code.google.com/p/android/issues/detail?id=212316 * <p> * Created by cattaka on 2017/01/12. */ public class Issue212316Parrier { public static final String DEFAULT_NAME = "Issue212316Parrier"; private static final String KEY_STORED_BUNDLE_ID = "net.cattaka.android.snippets.issue.Issue212316Parrier.KEY_STORED_BUNDLE_ID"; private String mName; private Context mContext; private String mAppVersionName; private int mAppVersionCode; private SharedPreferences mPreferences; private File mDirForStoredBundle; public Issue212316Parrier(Context context, String appVersionName, int appVersionCode) { this(context, appVersionName, appVersionCode, DEFAULT_NAME); } public Issue212316Parrier(Context context, String appVersionName, int appVersionCode, String name) { mName = name; mContext = context; mAppVersionName = appVersionName; mAppVersionCode = appVersionCode; } public void initialize() { mPreferences = mContext.getSharedPreferences(mName, Context.MODE_PRIVATE); File cacheDir = mContext.getCacheDir(); mDirForStoredBundle = new File(cacheDir, mName); if (!mDirForStoredBundle.exists()) { mDirForStoredBundle.mkdirs(); } long lastStoredBundleId = 1; boolean needReset = true; String fingerPrint = (Build.FINGERPRINT != null) ? Build.FINGERPRINT : ""; needReset = !fingerPrint.equals(mPreferences.getString("deviceFingerprint", null)) || !mAppVersionName.equals(mPreferences.getString("appVersionName", null)) || (mAppVersionCode != mPreferences.getInt("appVersionCode", 0)); lastStoredBundleId = mPreferences.getLong("lastStoredBundleId", 1); if (needReset) { clearDirForStoredBundle(); mPreferences.edit() .putString("deviceFingerprint", Build.FINGERPRINT) .putString("appVersionName", mAppVersionName) .putInt("appVersionCode", mAppVersionCode) .putLong("lastStoredBundleId", lastStoredBundleId) .apply(); } } /** * Call this from {@link android.app.Activity#onCreate(Bundle)}, {@link android.app.Activity#onRestoreInstanceState(Bundle)} or {@link android.app.Activity#onPostCreate(Bundle)} */ public void restoreSaveInstanceState(@Nullable Bundle savedInstanceState, boolean deleteStoredBundle) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (savedInstanceState != null && savedInstanceState.containsKey(KEY_STORED_BUNDLE_ID)) { long storedBundleId = savedInstanceState.getLong(KEY_STORED_BUNDLE_ID); File storedBundleFile = new File(mDirForStoredBundle, storedBundleId + ".bin"); Bundle storedBundle = loadBundle(storedBundleFile); if (storedBundle != null) { savedInstanceState.putAll(storedBundle); } if (deleteStoredBundle && storedBundleFile.exists()) { storedBundleFile.delete(); } } } } /** * Call this from {@link android.app.Activity#onSaveInstanceState(Bundle)} */ public void saveInstanceState(Bundle outState) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (outState != null) { long nextStoredBundleId = mPreferences.getLong("lastStoredBundleId", 1) + 1; mPreferences.edit().putLong("lastStoredBundleId", nextStoredBundleId).apply(); File storedBundleFile = new File(mDirForStoredBundle, nextStoredBundleId + ".bin"); saveBundle(outState, storedBundleFile); outState.clear(); outState.putLong(KEY_STORED_BUNDLE_ID, nextStoredBundleId); } } } private void saveBundle(@NonNull Bundle bundle, @NonNull File storedBundleFile) { byte[] blob = marshall(bundle); OutputStream out = null; try { out = new GZIPOutputStream(new FileOutputStream(storedBundleFile)); out.write(blob); out.flush(); out.close(); } catch (IOException e) { // ignore } finally { if (out != null) { try { out.close(); } catch (IOException e) { // ignore } } } } @Nullable private Bundle loadBundle(File storedBundleFile) { byte[] blob = null; InputStream in = null; try { in = new GZIPInputStream(new FileInputStream(storedBundleFile)); ByteArrayOutputStream bout = new ByteArrayOutputStream(); int n; byte[] buffer = new byte[1024]; while ((n = in.read(buffer)) > -1) { bout.write(buffer, 0, n); // Don't allow any extra bytes to creep in, final write } bout.close(); blob = bout.toByteArray(); } catch (IOException e) { // ignore } finally { if (in != null) { try { in.close(); } catch (IOException e) { // ignore } } } try { return (blob != null) ? (Bundle) unmarshall(blob) : null; } catch (Exception e) { return null; } } private void clearDirForStoredBundle() { for (File file : mDirForStoredBundle.listFiles()) { if (file.isFile() && file.getName().endsWith(".bin")) { file.delete(); } } } @NonNull private static <T extends Parcelable> byte[] marshall(@NonNull final T object) { Parcel p1 = Parcel.obtain(); p1.writeValue(object); byte[] data = p1.marshall(); p1.recycle(); return data; } @SuppressWarnings("unchecked") @NonNull private static <T extends Parcelable> T unmarshall(@NonNull byte[] bytes) { Parcel p2 = Parcel.obtain(); p2.unmarshall(bytes, 0, bytes.length); p2.setDataPosition(0); T result = (T) p2.readValue(Issue212316Parrier.class.getClassLoader()); p2.recycle(); return result; } } 

Full codes: https://github.com/cattaka/AndroidSnippets/pull/37

I worry that Parcel # marshall should not be used for persistent. But I have no other idea.

+1
Jan 12 '17 at 6:25
source share

None of the answers above worked for me, the reason for this problem was quite simple, because I used some of them FragmentStatePagerAdapter, and the saveState method saves the state of the fragments, because one of my fragments was quite large, so saving this fragment leads to this TransactionTooLargeExecption .

I tried to override the saveState method in my pager implementation as indicated by @ IK828, but this could not solve the problem.

In my fragment there was an EditText, which was used to store very large text, which was the culprit of the problem in my case, so just in the onPause () of the fragment I set the edittext text to an empty line. i.e:

 @Override public void onPause() { edittext.setText(""); } 

Now that the FragmentStatePagerAdapter tries to save state, this large piece of text will not be there to consume most of it, therefore, it resolves the failure.

In your case, you need to find what is the culprit, it can be an ImageView with some bitmap, a TextView with a huge chunk of text, or any other high memory consumption, you need to free up memory, you can set the image to .setImageResource (null) or similar in onPause () of your fragment.

update: onSaveInstanceState is better for this purpose before calling super:

 @Override public void onSaveInstanceState(Bundle outState) { edittext.setText(""); super.onSaveInstanceState(outState); } 

or as @Vladimir pointed out, you can use android: saveEnabled = "false" or view.setSaveEnabled (false); in the view or user view and make sure it is set to onResume, otherwise it will be empty when the action resumes.

+1
Nov 20 '17 at 18:45
source share

Because Android N changes its behavior and throws a TransactionTooLargeException instead of reporting an error.

  try { if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Reporting activity stopped: " + activity); ActivityManagerNative.getDefault().activityStopped( activity.token, state, persistentState, description); } catch (RemoteException ex) { if (ex instanceof TransactionTooLargeException && activity.packageInfo.getTargetSdkVersion() < Build.VERSION_CODES.N) { Log.e(TAG, "App sent too much data in instance state, so it was ignored", ex); return; } throw ex.rethrowFromSystemServer(); } 

My solution is to hook up an instance of ActivityMangerProxy and try to catch the activityStopped method.

Here is the code:

 private boolean hookActivityManagerNative() { try { ClassLoader loader = ClassLoader.getSystemClassLoader(); Field singletonField = ReflectUtils.findField(loader.loadClass("android.app.ActivityManagerNative"), "gDefault"); ReflectUtils.ReflectObject singletonObjWrap = ReflectUtils.wrap(singletonField.get(null)); Object realActivityManager = singletonObjWrap.getChildField("mInstance").get(); Object fakeActivityManager = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{loader.loadClass("android.app.IActivityManager")}, new ActivityManagerHook(realActivityManager)); singletonObjWrap.setChildField("mInstance", fakeActivityManager); return true; } catch (Throwable e) { AppHolder.getThirdPartUtils().markException(e); return false; } } private static class ActivityManagerHook implements InvocationHandler { private Object origin; ActivityManagerHook(Object origin) { this.origin = origin; } public Object getOrigin() { return origin; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { switch (method.getName()) { //ActivityManagerNative.getDefault().activityStopped(activity.token, state, persistentState, description); case "activityStopped": { try { return method.invoke(getOrigin(), args); } catch (Exception e) { e.printStackTrace(); } return null; } } return method.invoke(getOrigin(), args); } } 

And the auxiliary reflex class

 public class ReflectUtils { private static final HashMap<String, Field> fieldCache = new HashMap<>(); private static final HashMap<String, Method> methodCache = new HashMap<>(); public static Field findField(Class<?> clazz, String fieldName) throws Throwable { String fullFieldName = clazz.getName() + '#' + fieldName; if (fieldCache.containsKey(fullFieldName)) { Field field = fieldCache.get(fullFieldName); if (field == null) throw new NoSuchFieldError(fullFieldName); return field; } try { Field field = findFieldRecursiveImpl(clazz, fieldName); field.setAccessible(true); fieldCache.put(fullFieldName, field); return field; } catch (NoSuchFieldException e) { fieldCache.put(fullFieldName, null); throw new NoSuchFieldError(fullFieldName); } } private static Field findFieldRecursiveImpl(Class<?> clazz, String fieldName) throws NoSuchFieldException { try { return clazz.getDeclaredField(fieldName); } catch (NoSuchFieldException e) { while (true) { clazz = clazz.getSuperclass(); if (clazz == null || clazz.equals(Object.class)) break; try { return clazz.getDeclaredField(fieldName); } catch (NoSuchFieldException ignored) { } } throw e; } } public static Method findMethodExact(Class<?> clazz, String methodName, Class<?>... parameterTypes) throws Throwable { String fullMethodName = clazz.getName() + '#' + methodName + getParametersString(parameterTypes) + "#exact"; if (methodCache.containsKey(fullMethodName)) { Method method = methodCache.get(fullMethodName); if (method == null) throw new NoSuchMethodError(fullMethodName); return method; } try { Method method = clazz.getDeclaredMethod(methodName, parameterTypes); method.setAccessible(true); methodCache.put(fullMethodName, method); return method; } catch (NoSuchMethodException e) { methodCache.put(fullMethodName, null); throw new NoSuchMethodError(fullMethodName); } } /** * Returns an array of the given classes. */ public static Class<?>[] getClassesAsArray(Class<?>... clazzes) { return clazzes; } private static String getParametersString(Class<?>... clazzes) { StringBuilder sb = new StringBuilder("("); boolean first = true; for (Class<?> clazz : clazzes) { if (first) first = false; else sb.append(","); if (clazz != null) sb.append(clazz.getCanonicalName()); else sb.append("null"); } sb.append(")"); return sb.toString(); } /** * Retrieve classes from an array, where each element might either be a Class * already, or a String with the full class name. */ private static Class<?>[] getParameterClasses(ClassLoader classLoader, Object[] parameterTypes) throws ClassNotFoundException { Class<?>[] parameterClasses = null; for (int i = parameterTypes.length - 1; i >= 0; i--) { Object type = parameterTypes[i]; if (type == null) throw new ClassNotFoundException("parameter type must not be null", null); if (parameterClasses == null) parameterClasses = new Class<?>[i + 1]; if (type instanceof Class) parameterClasses[i] = (Class<?>) type; else if (type instanceof String) parameterClasses[i] = findClass((String) type, classLoader); else throw new ClassNotFoundException("parameter type must either be specified as Class or String", null); } // if there are no arguments for the method if (parameterClasses == null) parameterClasses = new Class<?>[0]; return parameterClasses; } public static Class<?> findClass(String className, ClassLoader classLoader) throws ClassNotFoundException { if (classLoader == null) classLoader = ClassLoader.getSystemClassLoader(); return classLoader.loadClass(className); } public static ReflectObject wrap(Object object) { return new ReflectObject(object); } public static class ReflectObject { private Object object; private ReflectObject(Object o) { this.object = o; } public ReflectObject getChildField(String fieldName) throws Throwable { Object child = ReflectUtils.findField(object.getClass(), fieldName).get(object); return ReflectUtils.wrap(child); } public void setChildField(String fieldName, Object o) throws Throwable { ReflectUtils.findField(object.getClass(), fieldName).set(object, o); } public ReflectObject callMethod(String methodName, Object... args) throws Throwable { Class<?>[] clazzs = new Class[args.length]; for (int i = 0; i < args.length; i++) { clazzs[i] = args.getClass(); } Method method = ReflectUtils.findMethodExact(object.getClass(), methodName, clazzs); return ReflectUtils.wrap(method.invoke(object, args)); } public <T> T getAs(Class<T> clazz) { return (T) object; } public <T> T get() { return (T) object; } } } 
0
Apr 21 '17 at 1:46
source share

In my case, I used TooLargeTool to track where the problem came from , and I found the key android:support:fragmentsin Bundlefrom mine was onSaveInstanceStateused up to almost 1 MB when the application crashed. So the solution was like:

 @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.remove("android:support:fragments"); } 

By doing this, I avoided preserving the state of all fragments and preserving other things that should be preserved.

0
Apr 26 '19 at 18:44
source share



All Articles