2011-01-18 15 views
6

Mam ponad 30 pojedynczych bitmap (320x240 pikseli), które chciałbym, aby wyświetlić jeden po drugim w pełnym ekranie na urządzeniach z Androidem powstałych w animacji. Obecnie zaimplementowałem animację za pomocą ImageView i Timera, który ustawia następną klatkę, a następnie wysyła wiadomość, która zastosuje następną klatkę. Wynikowa liczba klatek na sekundę jest bardzo niska: < 2 klatki na sekundę.Draw High Res animacje z dużą liczbą klatek na Androida

Timer:

animationTimer.scheduleAtFixedRate(new TimerTask() { 
    @Override 
    public void run() { 
     Drawable frame = getNextFrame(); 
      if (frame != null) { 
       Message message = animationFrameHandler.obtainMessage(1, frame); 
       animationFrameHandler.sendMessage(message); 
      } 
     } 
    }, 0, (int) (1000.0d/fps)); 

Handler:

final Handler animationFrameHandler = new Handler() { 
    @Override 
    public void handleMessage(Message message) { 
     setImageDrawable((Drawable) message.obj); 
    } 
}; 

Ponieważ chcę osiągnąć klatek do 30 kl./s muszę skorzystać z innego mechanizmu i słyszał Canvas.drawBitmapMesh() i OpenGL.

Jeśli to możliwe chciałbym uniknąć używając OpenGL.

Dziękuję bardzo za podzielenie się wrażeniami!

Odpowiedz

5

moje podejście obecnie pracuje jest następujący:

Przed rozpoczęciem animacji załadować każdą klatkę do List<Bitmap>. Ważne: zadzwoń pod numer System.gc(), jeśli otrzymujesz OutOfMemoryError s - co naprawdę pomaga w zapisaniu większej ilości bitmap do pamięci. Następnie uruchom wątek, który publikuje następną klatkę do instancji View, a następnie zaktualizuj jej kanwę.

Ładowanie ramki i rozpoczynając animację

// Loading the frames before starting the animation 
List<Bitmap> frames = new ArrayList<Bitmap>(); 
for (int i = 0; i < 30; i++) { 
    // Load next frame (e. g. from drawable or assets folder) 
    frames.add(...); 
    // Do garbage collection every 3rd frame; really helps loading all frames into memory 
    if (i %% 3 == 0) { 
     System.gc(); 
    } 
} 

// Start animation 
frameIndex = 0; 
animationThread.start(); 

wątku, który dotyczy następnej klatki

private final class AnimationThread extends Thread { 
    @Override 
    public void run() { 
     while (!isInterrupted()) { 
      // Post next frame to be displayed 
      animationView.postFrame(frames.get(frameIndex)); 

      // Apply next frame (restart if last frame has reached) 
      frameIndex++; 
      if (frameIndex >= frames.size()) { 
       frameIndex = 0; 
      } 

      try { 
       sleep(33); // delay between frames in msec (33 msec mean 30 fps) 
      } catch (InterruptedException e) { 
       break; 
      } 
     } 
    } 
} 

Widok animacja

class AnimationView extends View { 
    Bitmap frame = null; 

    public void postFrame(Bitmap frame) { 
     Message message = frameHandler.obtainMessage(0, frame); 
     frameHandler.sendMessage(message); 
    } 

    protected final Handler frameHandler = new Handler() { 
     @Override 
     public void handleMessage(Message message) { 
      if (message.obj != null) { 
       frame = (Bitmap) message.obj; 
      } else { 
       frame = null; 
      } 
      invalidate(); 
     } 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     if (frame == null) return; 
     canvas.drawARGB(0, 0, 0, 0); 
     canvas.drawBitmap(frame, null, null, null); 
    } 
} 
+0

jak "uruchomić timer, który publikuje następną klatkę do instancji View", możesz podać więcej szczegółów dziękuję – pengwang

+1

Witaj pengwang, zaktualizowałem swoją odpowiedź, aby dać więcej wglądu w moje podejście. nadal są niejasne informacje: –

+0

Dziękuję za wasze wojownicze – pengwang

0

Pozwolę komuś innemu zrobić to najlepiej, ale jedną rzecz, która natychmiast przychodzi mi do głowy z twojego postu, który nie pomaga, jest użycie TimerTask to straszny sposób na zrobienie tego i nie jest przeznaczony do animacji .

+0

Masz rację! W moim teście, jak robić animacje, wystarczyło. Jak już wspomniałem, FrameAnimation nie jest szybszy i nie pozwala na określenie, z której klatki ma się obracać, więc użycie TimerTask było dla mnie wygodne. –

0

Prawdopodobnie nie pomoże w wydajności, ale jeśli te bitmapy są zasobami, może warto rozważyć użycie numeru AnimationDrawable. Jeśli nie, spróbuj przedłużyć Drawable i zaimplementuj interfejs Animatable. Widoki mają już wbudowaną obsługę animowania rysunków, nie ma potrzeby używania do tego obsługi.

Jednym ze sposobów poprawienia wydajności może być dopasowanie głębi bitowej rysunków do tych w bieżącym oknie. Romain Guy wygłosił przemówienie na ten temat i ogólnie animacje: http://www.youtube.com/watch?v=duefsFTJXzc

+0

Masz rację, użycie AnimationDrawable jest tak wolne, jak moja implementacja. Będę rzucił okiem na myśl przewodnią. Dziękujemy jak dotąd! –

2

Powinieneś spojrzeć na klasę FrameAnimation; http://developer.android.com/guide/topics/graphics/2d-graphics.html#frame-animation do animacji klatek z animacji Androidy.

Chociaż może to być zbyt wolne.

Inną alternatywą, jeśli nie chcesz używać OpenGL ES, jest narysowanie na płótnie, o czym już wspominałeś. Ale po prostu użyj .drawBitmap, a nie drawBitmapMesh. Utwórz SurfaceView, który ma wątek, który wątek powinien narysować na Twoim kanwie w dowolnym przedziale czasowym.

Jest to bardzo proste, wystarczy przeczytać dokumentację systemu Android, wszystkie informacje są dostępne.

+0

Rzeczywiście animacja klatek jest zbyt wolna - pokazuje tę samą szybkość, co moja implementacja. Ponieważ muszę przestrzegać pewnych zasad, jak powtarzać ramki, zrobiłem własną implementację. Zajrzę do kombinacji SurfaceView/.drawBitmap i udzielę informacji tutaj. Dziękujemy jak dotąd! –

+0

Dzięki C0deAttack, studiowanie strony http://developer.android.com/guide/topics/graphics/index.html#on-surfaceview (On a SurfaceView) pomogło mi w implementacji wątku rysującego następną klatkę, aby uzyskać animację za pomocą SurfaceView. –

+0

Niestety przezroczysty SurfaceView nie może być warstwowany na innym SurfaceView, który jest używany do podglądu kamery "getHolder() .setType (SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS" "Powiedział, że używam teraz tylko widoku, który jest aktualizowany przez wiadomość jest wysyłany z wątku dostarczającego grafikę animacji, co niestety nie daje pożądanej wydajności, liczba klatek na sekundę> 10 fps jest prawie nieosiągalna na niskobudżetowych urządzeniach z Androidem, więc będę musiał zanurzyć się w OpenGL w kolejnych dniach. help! –

Powiązane problemy