2015-05-25 4 views
1

Я использовал следующий класс анимации, потому что у меня есть несколько изображений для создания анимации. После 7-й анимации я получаю OutofMemoryError. androidgraphics.Bitmap.createBitmapAndroid outofmemory bitmap

public class AnimationsContainer { 
public int FPS = 30; // animation FPS 

// single instance procedures 
private static AnimationsContainer mInstance; 

private AnimationsContainer() { 
}; 

public static AnimationsContainer getInstance() { 
    if (mInstance == null) 
     mInstance = new AnimationsContainer(); 
    return mInstance; 
} 

// animation progress dialog frames 
private int[] mProgressAnimFrames = {}; 

// animation splash screen frames 


/** 
* @param imageView 
* @return progress dialog animation 
*/ 
public FramesSequenceAnimation createProgressDialogAnim(ImageView imageView) { 
    return new FramesSequenceAnimation(imageView, mProgressAnimFrames); 
} 

/** 
* @param imageView 
* @return splash screen animation 
*/ 
public FramesSequenceAnimation createSplashAnim(ImageView imageView, int[] n) { 
    return new FramesSequenceAnimation(imageView, n); 
} 

/** 
* AnimationPlayer. Plays animation frames sequence in loop 
*/ 
public class FramesSequenceAnimation { 
private int[] mFrames; // animation frames 
private int mIndex; // current frame 
private boolean mShouldRun; // true if the animation should continue running. Used to stop the animation 
private boolean mIsRunning; // true if the animation currently running. prevents starting the animation twice 
private SoftReference<ImageView> mSoftReferenceImageView; // Used to prevent holding ImageView when it should be dead. 
private Handler mHandler; 
private int mDelayMillis; 
private OnAnimationStoppedListener mOnAnimationStoppedListener; 

private Bitmap mBitmap = null; 
private BitmapFactory.Options mBitmapOptions; 

public FramesSequenceAnimation(ImageView imageView, int[] frames) { 
    mHandler = new Handler(); 
    mFrames = frames; 
    mIndex = -1; 
    mSoftReferenceImageView = new SoftReference<ImageView>(imageView); 
    mShouldRun = false; 
    mIsRunning = false; 
    mDelayMillis = 50; 

    imageView.setImageResource(mFrames[0]); 

    // use in place bitmap to save GC work (when animation images are the same size & type) 
    if (Build.VERSION.SDK_INT >= 11) { 
     Bitmap bmp = ((BitmapDrawable) imageView.getDrawable()).getBitmap(); 
     int width = bmp.getWidth(); 
     int height = bmp.getHeight(); 
     Bitmap.Config config = bmp.getConfig(); 
     mBitmap = Bitmap.createBitmap(width, height, config); 
     mBitmapOptions = new BitmapFactory.Options(); 
     // setup bitmap reuse options. 
     mBitmapOptions.inBitmap = mBitmap; 
     mBitmapOptions.inMutable = true; 
     mBitmapOptions.inSampleSize = 1; 
    } 
} 

private int getNext() { 
    mIndex++; 
    if (mIndex == mFrames.length){ 
     mIndex = mIndex - 1; 
    mShouldRun = false; 
    } 
    return mFrames[mIndex]; 
} 

/** 
* Starts the animation 
*/ 
public synchronized void start() { 
    mShouldRun = true; 
    if (mIsRunning) 
     return; 

    Runnable runnable = new Runnable() { 
     @Override 
     public void run() { 
      ImageView imageView = mSoftReferenceImageView.get(); 
      if (!mShouldRun || imageView == null) { 
       mIsRunning = false; 
       if (mOnAnimationStoppedListener != null) { 
        mOnAnimationStoppedListener.onAnimationStopped(); 
       } 
       return; 
      } 

      mIsRunning = true; 
      mHandler.postDelayed(this, mDelayMillis); 

      if (imageView.isShown()) { 
       int imageRes = getNext(); 
       if (mBitmap != null) { // so Build.VERSION.SDK_INT >= 11 
        Bitmap bitmap = null; 
        try { 
         bitmap = BitmapFactory.decodeResource(imageView.getResources(), imageRes, mBitmapOptions); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
        if (bitmap != null) { 
         imageView.setImageBitmap(bitmap); 
        } else { 
         imageView.setImageResource(imageRes); 
         mBitmap.recycle(); 
         mBitmap = null; 
        } 
       } else { 
        imageView.setImageResource(imageRes); 
       } 
      } 

     } 
    }; 

    mHandler.post(runnable); 
} 

    /** 
    * Stops the animation 
    */ 
    public synchronized void stop() { 
     mShouldRun = false; 
    } 
} 
} 

Может кто-нибудь объяснить мне, почему и скажите мне, как это исправить? Я уже добавил

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 

в мой файл манифеста.

+0

вы уверены, что это декодируется растровые 'растровой = BitmapFactory.decodeResource (imageView.getResources(), imageRes, mBitmapOptions);' всегда не ноль? Потому что, как только он будет равен нулю, каждый цикл загрузит новое изображение с помощью 'imageView.setImageResource (imageRes);', поэтому в конечном итоге будет исключение OOM. – Leo

+0

. Пожалуйста, прочитайте [Обучение разработчиков Android для растровых изображений] (https://developer.android. ком/обучение/отображающие-битовые/index.html) – StenSoft

ответ

0

Это может быть полезно, если вы не будете ссылаться на ненужные изображения. Это происходит потому, что у вас, вероятно, есть «стандартная» куча памяти 32 МБ или что-то подобное (возможно, 64 МБ или, может быть, 16 МБ). Если вы считаете, что большинство изображений составляет 5 МБ или более, неудивительно, что у тебя не хватает памяти.

Вы можете увеличить размер кучи с помощью android:largeHeap="true" так:

How to increase heap size of an android application?

Смежные вопросы