Provoquant OutOfMemoryError en en Animation image par Image dans Android
Je vais avoir beaucoup d'images comme des images dans mes ressources/drawable dossier (disons environ 200). Et d'utilisation de ces images que je veux exécuter une animation. La plus longue de l'animation est de 80Frames. Je suis avec succès en mesure d'exécuter l'animation sur cliquez sur les boutons pour certains, mais pour certains, de l'animation c'est de me donner OutOfMemoryError disant que la VM ne peut pas fournir une telle mémoire. Il est hors de VM Budget. Je compte la taille de toutes les images de ses environ 10 mo. La taille de chaque image est de 320x480 en pixels.
J'ai essayer de googler et a constaté que j'ai besoin d'appeler explicitement le Garbage Collector en utilisant le Système.gc() la méthode. Je l'ai fait mais j'obtiens des erreurs de temps de la mémoire. Quelqu'un peut merci de bien vouloir m'aider dans cette.
Code:-
ImageView img = (ImageView)findViewById(R.id.xxx);
img.setBackgroundResource(R.anim.angry_tail_animation);
AnimationDrawable mailAnimation = (AnimationDrawable) img.getBackground();
MediaPlayer player = MediaPlayer.create(this.getApplicationContext(), R.raw.angry);
if(mailAnimation.isRunning()) {
mailAnimation.stop();
mailAnimation.start();
if (player.isPlaying()) {
player.stop();
player.start();
}
else {
player.start();
}
}
else {
mailAnimation.start();
if (player.isPlaying()) {
player.stop();
player.start();
}
else {
player.start();
}
}
C'est le code que j'ai écrite sur le clic d'un Bouton.....
Fichier de ressources à l'intérieur de res/drawable/anim
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true" >
<item android:drawable="@drawable/cat_angry0000" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0001" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0002" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0003" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0004" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0005" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0006" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0007" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0008" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0009" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0010" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0011" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0012" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0013" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0014" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0015" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0016" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0017" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0018" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0019" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0020" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0021" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0022" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0023" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0024" android:duration="50"/>
<item android:drawable="@drawable/cat_angry0025" android:duration="50"/>
</animation-list>
** Ci-dessus est le fichier de ressource utilisée dans setBackgroundResource, de la même façon, je vais avoir 10 de plus fichier pour d'autres d'animation différentes. **
Journal Des Erreurs
01-16 22:23:41.594: E/AndroidRuntime(399): FATAL EXCEPTION: main
01-16 22:23:41.594: E/AndroidRuntime(399): java.lang.IllegalStateException: Could not execute method of the activity
01-16 22:23:41.594: E/AndroidRuntime(399): at android.view.View$1.onClick(View.java:2144)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.view.View.performClick(View.java:2485)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.view.View$PerformClick.run(View.java:9080)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.os.Handler.handleCallback(Handler.java:587)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.os.Handler.dispatchMessage(Handler.java:92)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.os.Looper.loop(Looper.java:123)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.app.ActivityThread.main(ActivityThread.java:3683)
01-16 22:23:41.594: E/AndroidRuntime(399): at java.lang.reflect.Method.invokeNative(Native Method)
01-16 22:23:41.594: E/AndroidRuntime(399): at java.lang.reflect.Method.invoke(Method.java:507)
01-16 22:23:41.594: E/AndroidRuntime(399): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
01-16 22:23:41.594: E/AndroidRuntime(399): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
01-16 22:23:41.594: E/AndroidRuntime(399): at dalvik.system.NativeStart.main(Native Method)
01-16 22:23:41.594: E/AndroidRuntime(399): Caused by: java.lang.reflect.InvocationTargetException
01-16 22:23:41.594: E/AndroidRuntime(399): at java.lang.reflect.Method.invokeNative(Native Method)
01-16 22:23:41.594: E/AndroidRuntime(399): at java.lang.reflect.Method.invoke(Method.java:507)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.view.View$1.onClick(View.java:2139)
01-16 22:23:41.594: E/AndroidRuntime(399): ... 11 more
01-16 22:23:41.594: E/AndroidRuntime(399): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
01-16 22:23:41.594: E/AndroidRuntime(399): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:460)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.content.res.Resources.loadDrawable(Resources.java:1709)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.content.res.Resources.getDrawable(Resources.java:581)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.graphics.drawable.AnimationDrawable.inflate(AnimationDrawable.java:267)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:787)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.graphics.drawable.Drawable.createFromXml(Drawable.java:728)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.content.res.Resources.loadDrawable(Resources.java:1694)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.content.res.Resources.getDrawable(Resources.java:581)
01-16 22:23:41.594: E/AndroidRuntime(399): at android.view.View.setBackgroundResource(View.java:7533)
01-16 22:23:41.594: E/AndroidRuntime(399): at talking.cat.CatActivity.middleButtonClicked(CatActivity.java:83)
Même façon, j'ai des boutons différents pour les différentes animations...
Grâce
- Ouais copain c'est un gros problème d'android.J'ai toujours face à elle, mais didnot trouver la solution particulière mais.. 😉
- Merci pour votre réponse, mais j'ai besoin de trouver quelque chose pour cela.......
- Pouvez-vous poster le code ici.... qui peut nous aider à mieux comprendre ...
- de quoi êtes-vous tester sur? Un véritable dispositif, à l'émulateur?
- Je suis en train de tester sur Émulateur en ce moment...
- Merci pour votre réponse..Voir maintenant que j'ai mis quelques extrait du code....
- S'il vous plaît tout un ayant aucune idée de me le faire savoir, j'ai vraiment besoin d'une solution pour ce. Merci
- est-il possible que vous ne donnez pas votre émulateur assez de RAM?
- avez-vous lu cela? developer.android.com/resources/articles/... je ne peux pas être sûr si c'est le problème (car vous n'avez qu'à condition de code pour le bouton de onClickListener), mais il est intéressant de lire... fuite de l'ensemble de l'Activité du contexte n'est jamais une bonne chose. serait-ce la question?
- plus de code serait utile si vous voulez quelqu'un pour essayer de trouver le problème :).
- Merci pour votre réponse. Compte tenu de 512 MO de mémoire pour l'émulateur, et modifier la mémoire par défaut dans eclipse.fichier ini à partir de 256 mo à 512 mo. Je n'ai pas lu l'article, mais maintenant il. Merci encore une fois
- J'ai posté tout le code ici. Reste des choses sont les mêmes que ci-dessus. Ce qui va changer, c'est la ressource de fichier, les fichiers audio et rien d'autre. Puis aussi j'ai essayer de mettre tout.
Vous devez vous connecter pour publier un commentaire.
Je suppose que votre image d'animation les images sont compressées (format PNG ou JPG). La taille compressée n'est pas utile pour le calcul de la quantité de mémoire nécessaire pour les afficher. Pour cela, vous devez penser à la taille non compressée. Ce sera le nombre de pixels (320 x 480), multiplié par le nombre d'octets par pixel, ce qui est généralement 4 (32 bits). Pour vos images, puis, chacun sera 614,400 octets. Pour le 26-animation d'images exemple fourni par vous, qui nécessitera un total de 15,974,400 octets pour tenir les premières données de l'image pour toutes les images, sans compter l'objet de frais généraux.
Regardant le code source pour
AnimationDrawable
, il apparaît pour charger toutes les images dans la mémoire à la fois, qu'il aurait fait de faire de bonnes performances.Si vous pouvez allouer plus de mémoire ou pas est très dépendante du système. Je voudrais au moins vous recommandons d'essayer cela sur un périphérique réel au lieu de l'émulateur. Vous pouvez également essayer de peaufiner l'émulateur disponible de la taille de la RAM, mais c'est juste deviner.
Il y a des façons d'utiliser
BitmapFactory.inPreferredConfig
pour charger des images dans un plus efficace de la mémoire format RVB 565 (plutôt que ARGB 8888). Cela permettrait d'économiser de l'espace, mais encore, elle pourrait ne pas être suffisante.Si vous ne pouvez pas allouer beaucoup de mémoire à la fois, vous devez considérer d'autres options. La plupart des cartes graphiques hautes performances des applications (ex: jeux) tirer leurs graphiques à partir des combinaisons de petits graphiques (sprites) ou 2D ou 3D primitives (rectangles, triangles). Dessin plein écran bitmap pour chaque trame est effectivement la même que le rendu de la vidéo, pas nécessairement la plus efficace.
L'ensemble du contenu de votre changement de l'animation avec chaque image? Une autre optimisation peut être pour animer la partie qui change réellement, et découpez vos bitmaps de tenir compte de cela.
Pour résumer, vous avez besoin de trouver un moyen d'attirer votre animation en utilisant moins de mémoire. Il y a beaucoup d'options, mais cela dépend beaucoup de la façon dont votre animation doit regarder.
addFrame(Drawable, int)
passer votre propre un drawable, aussi créé dans le code à l'aide deBitmapDrawable
pour envelopperBitmap
s créés à l'aide deBitmapFactory
. Ou vous pourriez essayer de créer votre propre sous-classe deDrawableContainer
(la super-classe deAnimationDrawable
) le plus adapté à vos besoins. OU, vous pouvez simplement créer un jeu de style de dessin de la boucle qui se déclenche le plus souvent possible, mais pas plus vite que votre taux de rafraîchissement et charges les images à partir des ressources dans une sorte de smart cache.J'ai eu le même problème. Android charge tous les un drawable à la fois, afin d'animation avec de nombreux cadres sont les causes de cette erreur.
J'ai fini par créer mon propre simple animation de la séquence:
Utilisation:
J'ai passé beaucoup de temps sur ce sujet et ont deux solutions différentes, à la fois bon..
Tout d'abord, le problème:
1) Android charge toutes les images dans la mémoire vive, en non compressé en format Bitmap.
2) Android utilise les ressources de mise à l'échelle, de sorte que sur un téléphone avec un xxxhdpi d'affichage (comme le LG G3), chaque image prend une TONNE d'espace, de sorte que vous rapidement à court de RAM.
Solution #1
1) court-circuite Android ressource mise à l'échelle. 2) les Magasins de la bytearrays de tous les fichiers dans la mémoire (ce sont de petites, surtout pour les Jpeg). 3) Génère des images bitmap, image par image, de sorte qu'il est presque impossible de faire fonctionner de la mémoire vive.
Inconvénients: Elle spams vos journaux qu'Android est l'allocation de mémoire pour de nouvelles images Bitmaps et de recyclage des anciens. Il effectue aussi moche sur des appareils plus anciens (Galaxy S1), mais qui joue bien sur le budget actuel des téléphones (lire: $10 Alcatel C1, j'ai ramassé au BestBuy). Deuxième solution ci-dessous fonctionne mieux sur les appareils plus anciens, mais pourraient encore à court de RAM dans certaines circonstances.
** Solution n ° 2 **
Il charge la ressource XML, analyse les charges et les ressources brutes - en contournant Android ressource mise à l'échelle (qui est responsable de la plupart des OutOfMemoryExceptions), et crée une AnimationDrawable.
Avantages: fonctionne mieux sur les appareils plus anciens (par exemple. Galaxy S1)
Inconvénients: toujours à court de RAM que c'est la tenue de tous les non compressé des images dans la mémoire (mais ils sont plus petits car ils ne sont pas mis à l'échelle de la façon dont Android normalement échelles images)
Si vous rencontrez toujours des problèmes de mémoire, l'utilisation de plus petites images... ou stocker le nom de la ressource + la durée, et de générer le tableau d'octets + Dessinés sur chaque image. Que serait certainement causer trop de découper entre les images, mais utilise presque zéro RAM.
J'ai créé une animation en classe qui affiche les images basée sur passé dans un drawable ressources et les cadres des durées.
Elle s'utilise comme ceci:
et dans onCreate:
J'ai eu ce problème et l'a résolu par faire les deux choses suivantes:
Mon animation a toujours pas de charge sur certains téléphones, après avoir fait l'étape 1.
Étape 2 l'ai eu à travailler sur ces téléphones.
Espère que cela sauve quelqu'un d'autre peu de temps.
EDIT: j'avais toujours des plantages après l'Activité, qui joue le AnimationDrawable mais je l'ai déjà travaillé. Voici les choses que j'ai fait:
Voici le code que j'utilise pour la création de la AnimationDrawable:
Et le code pour libérer les images lorsque vous avez terminé de les utiliser. Vous pourriez le faire dans OnPause ou OnDestroy. _loadingAnimation est mon AnimationDrawable créé ci-dessus. J'aimerais savoir ce que SetCallback() le fait pour vous dans ce cas. J'ai juste copié qu'à partir de quelque part d'autre sur soi.
Ted
string
au lieu deString
, etc?Similaire à d'autres réponses, à l'aide de rxjava:
J'ai porté une solution à Xamarin Android et fait quelques améliorations.
Fonctionne très bien avec les changements d'orientation et spécialement avec des images autour de 300 de largeur et de hauteur (la plus grande de l'image, plus il faut de temps pour charger l'image, plus de scintillement).
C'est mon écran de démarrage de classe: (cette classe lit les images à partir du dossier drawable qui sont nommés "splash_0001, splash_0002 ...". Donc pas besoin de le nom de votre image à des ressources sur un tableau. Augmenter le nombre d'images par seconde (FPS) à la vitesse de l'animation).
C'est le grand problème avec le sdk, mais il peut être résolu par l'utilisation de threads pour simultanément le chargement des images bitmap au lieu de charger la totalité de l'image en même temps.
J'ai résolu mon outOfMemoryError problème en coupant le framerate brutalement et de mise à l'échelle vers le bas les images dans gimp. En fonction de ce que vous faites, vous pouvez probablement vous en sortir avec beaucoup moins de fps que vous attendez.
- Je résoudre ce problème par mettre toutes les images dans la gamme et l'utilisation retard après montrent chacune d'elles.
Le tableau des images source dans res/string
<!-- Array table for the pictures to show on the spinner-->
<array name="spinner_list">
<item>@drawable/arrows_loop__00000_org</item>
<item>@drawable/arrows_loop__00005_org</item>
<item >@drawable/arrows_loop__00010_org</item>
<item>@drawable/arrows_loop__00015_org</item>
<item >@drawable/arrows_loop__00020_org</item>
<item >@drawable/arrows_loop__00025_org</item>
.
.
.
</array>
Je déclare sur l'spinner imageView
private static ImageView imagespinner;
Puis dans ma classe, je l'appelle ici:
puis sur runimage-je faire la boucle avec retard comme ceci:
public void runimage(final TypedArray tableau, int index) {
donc, je lance toutes les images avec 55milsec de retard sur le imagespinner. Après avoir fini de faire le nex travail.