web-dev-qa-db-fra.com

TransactionTooLargeException uniquement sur Nougat

Je suis une application qui fonctionne bien sur les appareils avec des versions Android inférieures à Nougat.

Lorsque je lance l'application sur un appareil avec Nougat et que j'appuie sur le bouton d'accueil, l'application se bloque et, dans logcat, j'ai:

!!! FAILED BINDER TRANSACTION !!!  (parcel size = 1819712)
Unhandled exception
Java.lang.RuntimeException: Android.os.TransactionTooLargeException: data parcel size 1819712 bytes
    at Android.app.ActivityThread$StopInfo.run(ActivityThread.Java:3781)
    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:6119)
    at Java.lang.reflect.Method.invoke(Native Method)
    at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:886)
    at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:776)
 Caused by: Android.os.TransactionTooLargeException: data parcel size 1819712 bytes
    at Android.os.BinderProxy.transactNative(Native Method)
    at Android.os.BinderProxy.transact(Binder.Java:615)
    at Android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.Java:3636)
    at Android.app.ActivityThread$StopInfo.run(ActivityThread.Java:3773)
    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:6119) 
    at Java.lang.reflect.Method.invoke(Native Method) 
    at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:886) 
    at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:776) 

Y-a-t-il une solution simple? Ce problème n'apparaît que sur le Nougat.

5
nuka_cola

J'ai le même problème. Cela a été déploré par de nombreux développeurs sur le forum google. Leur réponse est WAI (fonctionne comme prévu) car ils ne recommandent pas de sauvegarder trop de données dans l'état. Il est donc conseillé d’ajouter uniquement des arguments très élémentaires à une intention. Si vous souhaitez envoyer des données entre activités ou fragments, 

  • Stockez les données dans un fichier (temporaire) et transmettez l'URI du fichier. Cette option est probablement votre seule option si vous souhaitez transférer De grandes quantités de données vers une application complètement différente. Stockez les données Dans l'instance d'application; 
  • Créez un conteneur singleton contenant les données Que vous transmettez.
  • Si vous utilisez FragmentStatePageAdapter, ajoutez le code suivant pour éviter qu'il enregistre des données d'état.

    @Override    
    public Parcelable saveState() {
            Bundle bundle = (Bundle) super.saveState();
            bundle.putParcelableArray("states", null); // Never maintain any states from the base class to avoid TransactionTooLargeException
            return bundle;
    }
    

Référence:

https://issuetracker.google.com/issues/37103380

https://www.neotechsoftware.com/blog/Android-intent-size-limit

5
flame3

De la documentation de la classe TransactionTooLargeException

Le tampon de transaction du classeur a une taille fixe limitée, actuellement1 Mo , qui est partagée par toutes les transactions en cours du processus. Par conséquent, cette exception peut être levée lorsque plusieurs transactions sont en cours, même lorsque la plupart des transactions individuelles sont de taille modérée.

Avez-vous vérifié la taille des données que vous transmettez sur l'API Android inférieure? 

Je suggère de consigner cette taille avant de transférer des données sur Android 7.0/7.1 et autres. Peut-être sur différentes versions d'Android, vos données occupent une quantité de mémoire différente.

1

cela se produit davantage s'il y a quelques fragments avec l'activité et que chacun effectue l'opération onSaveInstance. Si le fragment onCreateView doit toujours redémarrer la vue (aucun état de vue n'a besoin d'être restauré), alors rootview.setSaveFromParentEnabled (false); pour empêcher onSaveInstanceState () de la vue. Cela peut aider.

0
lannyf

Pareil ici. Pas de solution rapide à ce problème.

Ma solution consistait à stocker temporairement les données dans la base de données ou dans le fichier .

Je pense que ceci est également un meilleur modèle de conception pour la plupart des cas d'utilisation avec des données énormes.

0
Thorsten Weiskopf

J'ai résolu ce problème en sauvegardant les données dans un fichier. Merci pour toutes vos réponses.

0
nuka_cola