2010-08-25 53 views
0

我一直在試圖使一個簡單的動態壁紙出來的引導動畫。所以基本上我在我的可繪製文件夾中有大約50個.png。我可以將動畫設置爲10-20幀,效果很好。但是一旦我將其設置爲大約30幀...我會發生OutOfMemory錯誤。我希望也許有人可以看看我的代碼,也可以舉例說明如何實現更多框架?這將有助於這麼多,我一直在看這幾個小時> <動態壁紙OutOfMemory錯誤,當我有超過30幀

這裏是我的代碼:

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(); 
     } 



    } 
} 

這裏是一個logcat的,如果那會在所有幫助:

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

[動態壁紙動畫強制關閉的可能重複當我添加超過10幀?](http://stackoverflow.com/questions/3539406/live-wallpaper-animation-force-closing-when-i-add-more-than-10-frames) – 2010-08-25 08:29:12

+0

我回答了這個問題問題和你接受了答案。那你爲什麼再問一次? – 2010-08-25 08:30:58

回答

3

每次繪製畫布時只創建一個位圖並重新加載每個png。例如,創建一個簡單的例程,將每個圖像重新加載到相同的位圖分配中。我還建議你將png文件轉換成jpg文件,因爲png是一種無損格式。使用jpg,你可以稍微壓縮每一幀。

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.... 
     }} 

或者我想,如果你想在DrawAnim代碼鏈接到bootanimation

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

那麼你可以使用這只是

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

android.graphics.Bitmap.createScaledBitmap(Bitmap.java:340)意味着,Android會生成一個新的位圖,因爲您沒有正確使用drawable- * dpi文件夾......這會使您的內存使用量增加一倍

-1

返回在我最後一個公司,我在一個移動平臺上工作時,我們遇到了一些相當嚴重的性能問題。我們做了相當多的調查,但我們通常會發現,一切運行緩慢,並且無法確定原因。最後,我們去了芯片組供應商尋求幫助,以瞭解爲什麼事情運行緩慢。過了一段時間,他們回過頭來回答:「你執行的代碼太多了。」

有一定的道理。

在這裏可能有類似的答案:您使用的內存太多。

您只需要減少您使用的位圖的數量或大小。

0

您無法將如此多的位圖加載到內存中。

您可以將限制位數加載到內存中,以及何時需要顯示其他圖片。

你可以用位圖的recycle()方法釋放一些內存,並創建新的位圖。 如果您等待GC進行垃圾回收,則內存已經不夠用了。

關鍵的一點是,不要在視圖中顯示時加載太多的位圖和回收()。

+0

你知道任何我能看出來的例子嗎?展示最好的方式來製作像50+圖片文件的動畫嗎? – brybam 2010-09-09 02:47:27