2013-08-16 49 views
0

我有一個動態壁紙,它將每幀畫到畫布上來運行循環動畫。我有一個圖像,尺寸與屏幕的確切尺寸一致。我有一組400幀的大小完全適合屏幕的底部三分之一;這是動畫發生的地方。這裏是顯示它們的代碼:低幀率將位圖寫入畫布

public void updateBG() { 
    mHandler.removeCallbacks(mUpdateDisplay); 
    if (mVisible) { 
     mHandler.postDelayed(mUpdateDisplay, 40); 
    } 

    if (imagesLoaded < totalFrames) { 
     ShowLoadingProgress(); 
    } else { 
     SurfaceHolder holder = getSurfaceHolder(); 
     Canvas c = null; 
     try { 
      c = holder.lockCanvas(); 
      if (c != null) { 
       Paint p = new Paint(); 
       p.setAntiAlias(true); 
       c.drawRect(0, 0, c.getWidth(), c.getHeight(), p); 
       Rect destinationRect = new Rect(); 
       destinationRect.set(0, 0, canvasWidth, canvasHeight); 


       if (animStartX > 0 || animEndX > 0 || animStartY > 0 || animEndY > 0) { 
        c.drawBitmap(BitmapFactory.decodeByteArray(bitmapArray[totalFrames], 0, bitmapArray[totalFrames].length), null, destinationRect, p); 
        Rect destinationRectAnim = new Rect(); 
        destinationRectAnim.set(animX, animY, animX+animWidth, animY+animHeight); 
        c.drawBitmap(BitmapFactory.decodeByteArray(bitmapArray[bgcycle], 0, bitmapArray[bgcycle].length), null, destinationRectAnim, p); 
       } else { 
        c.drawBitmap(BitmapFactory.decodeByteArray(bitmapArray[bgcycle], 0, bitmapArray[bgcycle].length), null, destinationRect, p); 
       } 

      } 
     } finally { 
      if (c != null) 
       holder.unlockCanvasAndPost(c); 
     } 
     bgcycle++; 
    } 
} 

此代碼上的Xperia離子(雙核1.5GHz的CPU)上運行的在大約10-12 FPS和更壞的舊設備。當我以一半的屏幕分辨率保存整個幀時,情況會好得多。實際上,當我開始在屏幕分辨率下使用完整幀時(它本應消除了在每幀上插值的需要),情況會變得更糟。然後,當我開始使用這段代碼時,情況變得更糟,該代碼編寫了兩個位圖(可能是因爲它無法保存上一次運行的畫布的上半部分)。

我該如何優化?我寧願不保存完整的幀,因爲保存每幀的動畫部分確實減少了內存使用量。這裏感覺真的很不對勁,尤其是考慮到這是以3GHz的功率運行的。我曾經在450 MHz Pentium III上觀看電影。有什麼顯而易見的,我做錯了嗎?即使手機尺寸正確,手機仍然嘗試插入圖像嗎?

+0

最後,在AndEngine嘗試類似的應用後,我決定逐幀方法不適用於顯示視頻。相反,我決定轉向FFMpeg,希望能達到合理的幀率。 – Nicholas

回答

3

您正在解碼您的位圖在每一幀,它是昂貴的,它會產生垃圾,將觸發GC。您還在使用軟件渲染進行渲染。這裏是您的解決方案,以便:

  • 每一幀上不要再解碼位圖
  • 重複使用位圖對象(見BitmapFactory.Options.inBitmap)
  • 使用硬件加速(直接渲染成查看而不是SurfaceView。)軟件插值非常昂貴。
+0

我必須研究所有這些;在Java/Android開發中,我仍然非常綠色。你能告訴我你的意思是「不要在每一幀上重新解碼」嗎?我將圖像以JPEG格式存儲在字節數組中,這樣可以避免每幀上的io,但是如果我將它們存儲爲bmp,我會吃掉數百MB的內存我誤解了嗎?謝謝! – Nicholas

+0

另外,如果可能的話,儘量不要在你的'Paint'和'Rect'實例上重新創建對象,如果性能是在內存的話,我會認真考慮在內存中保存位圖。所有的關注點位圖解碼絕對是一個很大的因素 – kabuko

+0

你能指導我解釋一些代碼示例或者教程,尤其是view和surfaceView之間的區別嗎?Google只能指向我的答案,它通常非常直接,對於更有經驗的開發人員而言,我的書籍在活動中討論圖形渲染,我知道它們與活動壁紙有一些重要的區別。 – Nicholas