8
votes

Galaxy S4 et peut-être tous les téléphones HD? Erreur de mémoire hors de la mémoire

Donc, cette application que je travaille, fonctionne bien sur un très ancien téléphone Android 2.3.3. Toutefois, lors de la fonctionner sur le GS4, le GS4 jette des exceptions de mémoire chaque fois est nécessaire pour charger une ressource à partir des tiroirs, qui est prédéfini dans le XML.

05-08 10:37:20.113: E/dalvikvm-heap(25740): Out of memory on a 16777232-byte allocation.
05-08 10:37:20.123: I/dalvikvm(25740): "main" prio=5 tid=1 RUNNABLE
05-08 10:37:20.123: I/dalvikvm(25740):   | group="main" sCount=0 dsCount=0 obj=0x41187b38 self=0x40dd1b68
05-08 10:37:20.123: I/dalvikvm(25740):   | sysTid=25740 nice=0 sched=0/0 cgrp=apps handle=1074533852
05-08 10:37:20.123: I/dalvikvm(25740):   | state=R schedstat=( 0 0 0 ) utm=156 stm=1070 core=1
05-08 10:37:20.123: I/dalvikvm(25740):   at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:596)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:817)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.content.res.Resources.loadDrawable(Resources.java:2854)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.content.res.TypedArray.getDrawable(TypedArray.java:602)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.view.View.<init>(View.java:3460)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.view.ViewGroup.<init>(ViewGroup.java:446)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.widget.LinearLayout.<init>(LinearLayout.java:176)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.widget.LinearLayout.<init>(LinearLayout.java:172)
05-08 10:37:20.123: I/dalvikvm(25740):   at java.lang.reflect.Constructor.constructNative(Native Method)
05-08 10:37:20.123: I/dalvikvm(25740):   at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.view.LayoutInflater.createView(LayoutInflater.java:593)
05-08 10:37:20.123: I/dalvikvm(25740):   at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.view.LayoutInflater.onCreateView(LayoutInflater.java:666)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:691)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.view.LayoutInflater.inflate(LayoutInflater.java:467)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
05-08 10:37:20.123: I/dalvikvm(25740):   at com.travelstorysgps.travelstorys.FragmentConnect.onCreateView(FragmentConnect.java:73)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.support.v4.app.Fragment.performCreateView(Fragment.java:1460)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:911)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:429)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.os.Handler.handleCallback(Handler.java:725)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.os.Handler.dispatchMessage(Handler.java:92)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.os.Looper.loop(Looper.java:137)
05-08 10:37:20.123: I/dalvikvm(25740):   at android.app.ActivityThread.main(ActivityThread.java:5293)
05-08 10:37:20.123: I/dalvikvm(25740):   at java.lang.reflect.Method.invokeNative(Native Method)
05-08 10:37:20.123: I/dalvikvm(25740):   at java.lang.reflect.Method.invoke(Method.java:511)
05-08 10:37:20.123: I/dalvikvm(25740):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
05-08 10:37:20.123: I/dalvikvm(25740):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
05-08 10:37:20.123: I/dalvikvm(25740):   at dalvik.system.NativeStart.main(Native Method)
05-08 10:37:20.123: D/skia(25740): --- decoder->decode returned false
05-08 10:37:20.123: D/AndroidRuntime(25740): Shutting down VM
05-08 10:37:20.123: W/dalvikvm(25740): threadid=1: thread exiting with uncaught exception (group=0x41186ac8)
05-08 10:37:20.133: E/AndroidRuntime(25740): FATAL EXCEPTION: main
05-08 10:37:20.133: E/AndroidRuntime(25740): android.view.InflateException: Binary XML file line #2: Error inflating class <unknown>
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.view.LayoutInflater.createView(LayoutInflater.java:619)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.view.LayoutInflater.onCreateView(LayoutInflater.java:666)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:691)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.view.LayoutInflater.inflate(LayoutInflater.java:467)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at com.travelstorysgps.travelstorys.FragmentConnect.onCreateView(FragmentConnect.java:73)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.support.v4.app.Fragment.performCreateView(Fragment.java:1460)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:911)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:429)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.os.Handler.handleCallback(Handler.java:725)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.os.Handler.dispatchMessage(Handler.java:92)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.os.Looper.loop(Looper.java:137)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.app.ActivityThread.main(ActivityThread.java:5293)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at java.lang.reflect.Method.invokeNative(Native Method)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at java.lang.reflect.Method.invoke(Method.java:511)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at dalvik.system.NativeStart.main(Native Method)
05-08 10:37:20.133: E/AndroidRuntime(25740): Caused by: java.lang.reflect.InvocationTargetException
05-08 10:37:20.133: E/AndroidRuntime(25740):    at java.lang.reflect.Constructor.constructNative(Native Method)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.view.LayoutInflater.createView(LayoutInflater.java:593)
05-08 10:37:20.133: E/AndroidRuntime(25740):    ... 21 more
05-08 10:37:20.133: E/AndroidRuntime(25740): Caused by: java.lang.OutOfMemoryError
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:596)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:817)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.content.res.Resources.loadDrawable(Resources.java:2854)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.content.res.TypedArray.getDrawable(TypedArray.java:602)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.view.View.<init>(View.java:3460)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.view.ViewGroup.<init>(ViewGroup.java:446)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.widget.LinearLayout.<init>(LinearLayout.java:176)
05-08 10:37:20.133: E/AndroidRuntime(25740):    at android.widget.LinearLayout.<init>(LinearLayout.java:172)
05-08 10:37:20.133: E/AndroidRuntime(25740):    ... 24 more


9 commentaires

Certaines sorties logcat seraient bien :)


Comme vous avez demandé monsieur.


ressemble à un problème courant, pareil m'est arrivé


Quelle est la taille de votre image et combien d'images similaires avez-vous dans la même mise en page?


C'est vraiment étrange, il ne devrait pas avoir de problèmes, cela fonctionne bien sur 3 autres appareils plus anciens. Le GS4 devrait le gérer correctement.


L'avez-vous testé sur d'autres périphériques HD?


Je n'en ai pas, il n'y a que vraiment le HTC One, et cet autre téléphone HTC Verizon et le Sony Xperia Z qui sont tous true HD. Cependant, je l'ai testé sur ma tablette 720p et cela fonctionne parfaitement.


Hmm, comme Dan Hulme, demanda -> Quelle est la taille de vos images? Vous les avez dans différentes résolutions (digues-LDPI / -MDPI / -HDPI / -XDPI)?


Oui, j'ai 3 tailles différentes spécifiées, MDPI, HDPI, XXHDPI.


3 Réponses :


6
votes

J'ai découvert le problème. Les images de fond ne sont apparemment pas manipulées de manière très efficace, surtout pas pour un écran de 1920x1080. Vous devez utiliser une couleur XML personnalisée, une couleur plate ou un JPG 24 bits. Assez drôle, je viens de courir quelques tests et un JPEG 1920x1080 reprend 95,60 Ko tandis que la même image rendue comme un PNG occupe 929,09 Ko.

Alors j'ai fait des tests et j'ai constaté que les érables définis XML avec des gradients, etc. sont super rapides, j'ai ensuite essayé mon JPG 1920x1080 et c'était super rapide, alors j'ai mis dans un PNG 1920x1080 et obtenu l'erreur. C'est drôle pour moi car le PNG I a été défini au début des écrans HD était seulement 910x540 et j'aurais obtenu l'erreur.

Alors, leçon ici est si vous voulez une image d'image utilise un JPG.


6 commentaires

Je me demande pourquoi les petits fichiers image (comme 910x540 png) peuvent provoquer un débordement de la mémoire de la taille du tas VM. Mes clients sont exprimant le même problème avec leurs S4 et d'autres périphériques FullHD.Essai si j'utilise Android: Grandheap = "vrai" dans le manifeste. J'ai d'abord essayé d'obtenir la mémoire de tas: TextView Infoxt_ram = (TextView) FOYVISHYID (r.id.infotxt_ram); ActivityManager am = (ActivityManager) Ceci.GetsystService (Activity_service); infoxt_ram.setText (Am.getMemoryClass () + "MB"); Cela affiche 128 Mo!


Faisons un peu de mathématiques. 910x540x32bit (avec canal alpha) = 1,87 Mo. Mathématiquement, je devrais avoir été capable d'afficher 68 images de cette taille!?! OK, le processus lui-même mange également une grande quantité de cette taille, mais certaines petites images de E.G 910x540px ne devraient pas nous donner une erreur de stupéfiante. J'ai raison, n'est-ce pas?


J'utilise l'algorithme de compression JPEG et les caches bitmap ... My Galaxy S4 Crashes Mais mon Nexus 5 ne le fait pas! Nexus 5 a une quincaillerie et une mémoire presque identiques. Mais une chose que j'ai remarquée, c'est que GetMemoryClass donne S4 128m et N5 192M, c'est donc une différence substantielle, mais mon Nexus S ne se bloque pas et cela ne fait que 48M!


Je ne sais pas pourquoi pensez-vous que JPG et PNG sont traités différents puisque vous vous retrouvez toujours avec un calcul bitmap (4 x largeur x hauteur). 4 est pour la taille de l'octet de pixels RGBA.


@vbokan a raison. La différence de png vs jpeg est une différence dans la taille de fichier . Pour que ces fichiers soient utiles comme des images, ils doivent être décompressés, leur taille en mémoire sera toujours largeur * hauteur * 4 , que ce soit que ces données a été initialement comprimé avec PNG ou JPEG.


Et pourtant, peu importe, lorsque JPG est utilisé, il n'y avait pas de crash et quand PNG a été utilisé, il y avait un crash. Lorsque JPG est utilisé, Android fonctionne sensiblement plus rapidement et avec PNG sensiblement plus lentement. Donc, quelque part là-bas, quelque chose se passe, qui n'est pas expliqué, et il y a en effet une différence très évidente et réelle, même si vous ne pouvez pas l'expliquer.



7
votes

J'ai eu le même problème et que c'était le cas: Galaxy S4 et tous les dispositifs de résolution 1920 * 1080, enregistrement en xxHDPI dossier d'abord et s'il n'y a pas d'images spécifiques, elle Écheler les autres tailles comme xhdpi , ... donc j'ai déplacé mes images sur xxhdpi dossier et il est résolu!


0 commentaires

16
votes

(@ ARash's Reshant fournit une solution de contournement, mais c'est ma tentative d'expliquer pourquoi cela peut fonctionner.)

Vous avez donc une image assez importante dans le répertoire de ressources digue , vous y référez-la dans votre fichier XML de mise en page et obtenez une erreur de mémoire hors mémoire à l'exécution lorsque vous le gonflez.

Lors du chargement de ressources introactives, Android effectuera des pré-échelant si elle le juge nécessaire. Du Documentation officielle :

Sur la base de la densité de l'écran actuel, le système utilise toutes les ressources spécifiques à la taille ou à la densité de votre application et les affiche sans échelle. Si les ressources ne sont pas disponibles dans la densité correcte, le système charge les ressources par défaut et les écaille vers le haut ou le bas selon les besoins pour correspondre à la densité de l'écran actuel. Le système suppose que les ressources par défaut (celles d'un répertoire sans qualificatif de configuration) sont conçues pour la densité d'écran de base (MDPI), à moins qu'elles ne soient chargées à partir d'un répertoire de ressources spécifique à la densité.

Cela signifie 2 choses:

  1. S'il n'y a aucune ressource de la densité de l'environnement, l'application est en cours d'exécution, le système prendra une ressource d'une autre densité et d'échelle (haut ou bas) pour correspondre à la densité cible
  2. Ressources Mettez dans le répertoire digue est supposé cibler un MDPI densité

    Donc, vous utilisez actuellement un téléphone XXHDPI. Le système souhaite charger la ressource digue apprendre_more pour le peindre sur le widget ivlearnmore . Il le recherchera dans le drawable-xxhdpi en priorité mais ne le trouvera pas là-bas, alors prendra le plus proche qu'il trouve le plus proche, dans ce cas celui du digue répertoire (qu'il suppose de cibler la densité MDPI) et de le charger dans la mémoire à l'échelle de la mémoire IT par un facteur de 3 qui est beaucoup si votre fichier image était significativement gros et peut facilement nécessiter davantage de mémoire que celle disponible pour l'application (et provoquer une erreur de mémoire de mémoire).

    C'est aussi la raison pour laquelle il a été chargé d'amende sur votre ancien périphérique Crappy 2.3: le dispositif était le plus probable de la densité MDPI ou HDPI et le système n'a pas essayé de haut de gamme ni de l'a fait par un facteur de 1,5.

    L'essentiel ici étant que vous mettez une ressource adaptée à une densité XXHDPI (ou plus?) dans un répertoire MDPI.

    Vous avez donc plusieurs options:

    1. Fournissez une ressource de taille appropriée par densité (c'est-à-dire une dans chaque drawable - * répertoire): C'est le meilleur pour éviter tout problème, lorsque possible
    2. Si vous n'avez qu'une version de la ressource, placez-la dans le répertoire correspondant à sa densité ( digue étant équivalente à drawable-MDPI !), dans votre cas peut-être digue-xxhdpi (dépend de votre ressource)
    3. Mettez la ressource dans le répertoire drawable-nodpi , cela empêchera que le système d'effectuer toute pré-échelle de la ressource (mais cela est typiquement pour les ressources densité-agnostiques, par exemple que vous redimensionnez-vous à Runtime)

2 commentaires

Homme ... Merci beaucoup d'avoir expliqué cela .. J'ai finalement corrigé un problème majeur dans mon application. J'ai eu beaucoup de grandes images dans mon "digue" et causait la mémoire massive qui gaspille ... putain


C'est une bonne réponse.