2010-08-25 13 views
0

J'ai essayé de faire un simple fond d'écran en direct à partir d'une animation de démarrage. Donc, fondamentalement, j'ai environ 50 .pngs dans mon dossier drawable. Je suis en mesure de définir l'animation à environ 10-20 images et cela fonctionne très bien. Mais une fois que je l'ai mis à environ 30 images ... je reçois une erreur OutOfMemory. J'espérais peut-être que quelqu'un pourrait jeter un oeil à mon code et peut-être donner un exemple de la façon dont je pourrais réaliser plus de cadres? Cela aiderait tellement je l'ai regardé pendant des heures> <Live Wallpaper OutOfMemory Erreur quand j'ai plus de 30 images

Voici mon code:

package com.androidnetwork.animlivewp; 

import android.content.res.Resources; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.graphics.Matrix; 
import android.graphics.Paint; 
import android.os.Handler; 
import android.os.SystemClock; 
import android.service.wallpaper.WallpaperService; 
import android.util.Log; 
import android.view.MotionEvent; 
import android.view.SurfaceHolder; 

public class AnimatedLiveWallpaper extends WallpaperService { 

    private final Handler mHandler = new Handler(); 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
    } 

    @Override 
    public Engine onCreateEngine() { 
     return new CubeEngine(); 
    } 

    class CubeEngine extends Engine { 

     private final Paint mPaint = new Paint(); 
     private float mPosY; 
     private boolean mAnime = true; 
     private Matrix mMatrix = new Matrix(); 

     private final Runnable mDrawAnim = new Runnable() { 
      public void run() { 
       drawFrame(); 
      } 
     }; 
     private boolean mVisible; 

     private static final int NUM_RES = 30; 
     private final Bitmap[] mPics = new Bitmap[NUM_RES]; 
     CubeEngine() { 
      Resources res = getResources(); 
      for (int i = 0; i< NUM_RES; i++) { 
       int id = res.getIdentifier("boot_00" + (100 + (i + 1)), "drawable", "com.androidnetwork.animlivewp"); 
       mPics[i] = BitmapFactory.decodeResource(res, id); 
      } 
     } 

     @Override 
     public void onCreate(SurfaceHolder surfaceHolder) { 
      super.onCreate(surfaceHolder); 

      setTouchEventsEnabled(false); 
     } 

     @Override 
     public void onDestroy() { 
      super.onDestroy(); 
      mHandler.removeCallbacks(mDrawAnim); 
     } 

     @Override 
     public void onVisibilityChanged(boolean visible) { 
      mVisible = visible; 
      if (visible) { 
       drawFrame(); 
      } else { 
       mHandler.removeCallbacks(mDrawAnim); 
      } 
     } 

     @Override 
     public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { 
      super.onSurfaceChanged(holder, format, width, height); 

      float w = mPics[0].getWidth(); 
      float h = mPics[0].getHeight(); 
      float s = width/(float)w; 
      mMatrix.reset(); 
      mMatrix.setScale(s, s); 

      mPosY = (height - (h * s))/2f; 
      drawFrame(); 
     } 

     @Override 
     public void onSurfaceCreated(SurfaceHolder holder) { 
      super.onSurfaceCreated(holder); 
     } 

     @Override 
     public void onSurfaceDestroyed(SurfaceHolder holder) { 
      super.onSurfaceDestroyed(holder); 
      mVisible = false; 
      mHandler.removeCallbacks(mDrawAnim); 
     } 

     @Override 
     public void onOffsetsChanged(float xOffset, float yOffset, 
       float xStep, float yStep, int xPixels, int yPixels) { 
      drawFrame(); 
     } 


     @Override 
     public void onTouchEvent(MotionEvent event) { 
      if (event.getAction() == MotionEvent.ACTION_MOVE) { 
       mAnime = !mAnime; 
      } 
      super.onTouchEvent(event); 
     } 


     void drawFrame() { 
      final SurfaceHolder holder = getSurfaceHolder(); 

      Canvas c = null; 
      try { 
       c = holder.lockCanvas(); 
       if (c != null) { 
        // draw something 
        drawAnim(c); 
        //drawTouchPoint(c); 
       } 
      } finally { 
       if (c != null) holder.unlockCanvasAndPost(c); 
      } 

      // Reschedule the next redraw 
      mHandler.removeCallbacks(mDrawAnim); 
      if (mVisible && mAnime) { 
       mHandler.postDelayed(mDrawAnim, 1000/10); 
      } 
     } 


     private int idx = 0; 
     void drawAnim(Canvas c) { 
      c.save(); 
      c.translate(0, mPosY); 
      c.drawBitmap(mPics[idx], mMatrix, mPaint); 
      if (mAnime) ++idx; 
      if (idx == NUM_RES) idx = 0; 

      c.restore(); 
     } 



    } 
} 

Et voici un logcat si cela va aider tout:

08-22 19:45:05.508: ERROR/AndroidRuntime(12277): FATAL EXCEPTION: main 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277): java.lang.OutOfMemoryError: bitmap size exceeds VM budget 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at android.graphics.Bitmap.nativeCreate(Native Method) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at android.graphics.Bitmap.createBitmap(Bitmap.java:468) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at android.graphics.Bitmap.createBitmap(Bitmap.java:435) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:340) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:488) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:462) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:323) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:346) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:372) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at com.androidnetwork.animlivewp.AnimatedLiveWallpaper$CubeEngine.<init>(AnimatedLiveWallpaper.java:55) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at com.androidnetwork.animlivewp.AnimatedLiveWallpaper.onCreateEngine(AnimatedLiveWallpaper.java:32) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at android.service.wallpaper.WallpaperService$IWallpaperEngineWrapper.executeMessage(WallpaperService.java:814) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:61) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at android.os.Handler.dispatchMessage(Handler.java:99) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at android.os.Looper.loop(Looper.java:123) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at android.app.ActivityThread.main(ActivityThread.java:4627) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at java.lang.reflect.Method.invokeNative(Native Method) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at java.lang.reflect.Method.invoke(Method.java:521) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
    08-22 19:45:05.508: ERROR/AndroidRuntime(12277):  at dalvik.system.NativeStart.main(Native Method) 
+0

double possible de [papier peint en direct la fermeture de la force d'animation quand j'ajoute plus de 10 images?] (http://stackoverflow.com/questions/3539406/live-wallpaper-animation-force-closing-when-i-add-more-than-10-frames) –

+0

J'ai répondu à cette question question et toi accepté la réponse. Alors pourquoi demandez-vous encore? –

Répondre

3

Créez uniquement un bitmap et rechargez chaque png chaque fois que vous dessinez votre canevas. Par exemple, créez une routine simple qui rechargera chaque image dans la même allocation de bitmap. Je suggère également que vous convertissiez les fichiers png en fichiers jpg, car png est un format sans perte. Avec jpg, vous pouvez compresser chaque image légèrement.

public void updateBG() { 

idx += 1; 
if (idx == NUM_RES) {idx = 0;} 
switch (bgcycle) { 
    case 0: myBg = BitmapFactory.decodeResource(getResources(),R.drawable.frame1); break; 
    case 1: myBg = BitmapFactory.decodeResource(getResources(),R.drawable.frame2); break; 
    case 2: myBg = BitmapFactory.decodeResource(getResources(),R.drawable.frame3); break; 
      case etc.... 
     }} 

Ou je suppose que vous pouvez utiliser si vous souhaitez créer un lien vers le Bootanimation

int id = res.getIdentifier("boot_00" + (100 + (idx + 1)), "drawable", "com.androidnetwork.animlivewp"); 
      myBg = BitmapFactory.decodeResource(res, id); 

Puis dans votre code DrawAnim juste

updateBG(); 
c.drawBitmap(myBg, mMatrix, null); 
0

android.graphics.Bitmap.createScaledBitmap(Bitmap.java:340) signifie qu'Android génère un nouveau bitmap parce que vous n'avez pas utilisé les dossiers drawable- * dpi correctement ... ce qui peut doubler l'utilisation de votre mémoire.

-1

Retour Dans ma dernière entreprise, où je travaillais sur une plate-forme mobile, nous avions des problèmes de performance assez sérieux. Nous avons mené une bonne partie de l'enquête, mais nous avons généralement constaté que tout se passait lentement et qu'il était difficile de déterminer pourquoi. Finalement, nous sommes allés voir le vendeur du chipset pour savoir pourquoi les choses tournaient lentement. Après un certain temps, ils sont revenus avec la réponse: "vous exécutez trop de code."

Il y a une certaine vérité à cela.

Et une réponse similaire est probablement appropriée ici: vous utilisez trop de mémoire.

Vous avez juste besoin de réduire le nombre ou la taille des bitmaps que vous utilisez.

0

Vous ne pouvez pas charger autant de bitmap en mémoire.

Vous pouvez charger le bitmap du nombre limite dans la mémoire, et quand Il est nécessaire d'afficher une autre image.

Vous pouvez libérer de la mémoire avec la méthode recycle() de bitmap et créer un nouveau bitmap. Si vous attendez le GC à la récupération de place, la mémoire est déjà insuffisante.

Le point clé est de ne pas charger trop de bitmap et de recycle() lorsqu'il n'est pas affiché.

+0

connaissez-vous des exemples que je pourrais vérifier qui montrent la meilleure façon de faire une animation avec comme plus de 50 fichiers image? – brybam