Intereting Posts
Android – В чем разница между compileSDKVersion «Google Inc.: API Google: 22» и «22»? ImageView заполняет ширину или высоту родителя, но поддерживает соотношение сторон Как разбить активность Android в нескольких файлах Android: получить размеры изображения без его открытия Как избежать множественных триггеров в EditText во время ввода пользователем? Как запустить эмулятор Android для Intel x86 Atom без аппаратного ускорения в Windows 8 для API 21 и 19? Что такое ошибка INSTALL_PARSE_FAILED_NO_CERTIFICATES? Создайте рябь без прозрачности Как переместить / переименовать файл из внутреннего хранилища приложений во внешнее хранилище на Android? Android – установите долю Samba в коде Android – Webview применяет только заголовки к первоначальному запросу Сообщение об ошибке Android XML Есть ли способ получить список всех классов из .dex-файла? Android Firebase DynamiteModule: не удалось загрузить дескриптор модуля ViewPager PagerObserver не зарегистрирован

Анимация Drawable вызывает OutOfMemoryError при втором запуске в Android

В настоящее время я разрабатываю игру, и я пытаюсь использовать один AnimationDrawable, чтобы показать одну анимацию в главном меню. Когда я запускаю игру один раз, она работает отлично. Но если я нажму кнопку «Назад», когда я снова открою игру, это даст мне OutOfMemorryError. Если я попаду домой и вернусь к игре, она загрузится, но не покажет анимацию, она пуста, где она должна быть.

Я думаю, что когда он снова откроет игру, он пытается загрузить анимацию, но она уже загружена из предыдущего запуска, я могу как-то освободить эту память? Как я могу обработать это исключение?

Поиск вокруг я могу найти, что его общая проблема в Android, но я не мог найти ничего полезного.

Если это актуально, мои изображения 310×316, и у меня есть 114 кадров для загрузки, анимация загружается в xml.

Мой класс MainMenu:

public class MainMenuActivity extends Activity{ private String TAG = MainMenuActivity.class.getSimpleName(); ImageView rabbitMenu ; AnimationDrawable ad; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.mainmenu); rabbitMenu = (ImageView) findViewById(R.id.rabbitMenu); rabbitMenu.setImageResource(R.drawable.rabbit_menu_animation); ad = (AnimationDrawable) rabbitMenu.getDrawable(); } public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); ad.start(); } } 

Журнал ошибок:

 01-31 16:13:11.320: E/AndroidRuntime(19550): FATAL EXCEPTION: main 01-31 16:13:11.320: E/AndroidRuntime(19550): java.lang.OutOfMemoryError: bitmap size exceeds VM budget 01-31 16:13:11.320: E/AndroidRuntime(19550): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) 01-31 16:13:11.320: E/AndroidRuntime(19550): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:563) 01-31 16:13:11.320: E/AndroidRuntime(19550): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:439) 

Редактировать:

После предложения @OleGG и теперь второй запуск идет хорошо, но на третьем запуске я, по-видимому, пытаюсь использовать переработанное растровое изображение.

Поэтому я отказался от использования AnimationDrawable, и я использовал AsncTask для решения моей проблемы. Теперь я постоянно меняю фон ImageView на моем onProgressUpdate (). Не лучший подход, но теперь у меня нет никаких проблем! Вот мой код AsyncTask, если у кого-то такая же проблема!

 private class DrawRabbit extends AsyncTask<Void, Integer, Void> { private boolean running = true; private int fps = 24; private int frame = 10014; private String drawableName; @Override protected Void doInBackground(Void... params) { while (running){ try { if (frame == 10014) Thread.sleep(1000); else Thread.sleep(fps); if (frame < 10160) { frame++; publishProgress(frame); } else running = false; } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return null; } protected void onProgressUpdate(Integer... frame) { drawableName = "rm" + frame[0]; int res_id = getResources().getIdentifier(drawableName, "drawable", getPackageName()); rabbitFrame.setBackgroundResource(res_id); } } в private class DrawRabbit extends AsyncTask<Void, Integer, Void> { private boolean running = true; private int fps = 24; private int frame = 10014; private String drawableName; @Override protected Void doInBackground(Void... params) { while (running){ try { if (frame == 10014) Thread.sleep(1000); else Thread.sleep(fps); if (frame < 10160) { frame++; publishProgress(frame); } else running = false; } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return null; } protected void onProgressUpdate(Integer... frame) { drawableName = "rm" + frame[0]; int res_id = getResources().getIdentifier(drawableName, "drawable", getPackageName()); rabbitFrame.setBackgroundResource(res_id); } } 

Solutions Collecting From Web of "Анимация Drawable вызывает OutOfMemoryError при втором запуске в Android"

Вы должны освободить память, используемую растровыми изображениями, когда вы выходите из этого экрана. К сожалению, для более ранних версий Android (afaik это было «исправлено» с 3.0, но я могу ошибаться) память для растровых изображений выделяется через собственный код и, что грустно, память должна быть явно освобождена.

Итак, я полагаю, вы попробуете такой подход:

  1. Переместите код для AnimationDrawable в метод onResume ().
  2. Добавьте следующий код для освобождения памяти в onPause ().

     ad.stop(); for (int i = 0; i < ad.getNumberOfFrames(); ++i){ Drawable frame = ad.getFrame(i); if (frame instanceof BitmapDrawable) { ((BitmapDrawable)frame).getBitmap().recycle(); } frame.setCallback(null); } ad.setCallback(null); 

Надеюсь, это поможет вам.

Таким образом, мне удается решить мою проблему с помощью такого подхода:

Создал один AsyncTask для рисования

 private class DrawRabbit extends AsyncTask<Void, Integer, Void> { private int fps = 24; private int frame = 10014; private String drawableName; @Override protected Void doInBackground(Void... params) { while (running){ try { if (frame == 10014) Thread.sleep(1000); else Thread.sleep(fps); if (frame < 10160) { frame++; publishProgress(frame); } else running = false; } catch (InterruptedException e) { e.printStackTrace(); } } return null; } protected void onProgressUpdate(Integer... frame) { drawableName = "rm" + frame[0]; int res_id = getResources().getIdentifier(drawableName, "drawable", getPackageName()); rabbitFrame.setBackgroundResource(res_id); } } в private class DrawRabbit extends AsyncTask<Void, Integer, Void> { private int fps = 24; private int frame = 10014; private String drawableName; @Override protected Void doInBackground(Void... params) { while (running){ try { if (frame == 10014) Thread.sleep(1000); else Thread.sleep(fps); if (frame < 10160) { frame++; publishProgress(frame); } else running = false; } catch (InterruptedException e) { e.printStackTrace(); } } return null; } protected void onProgressUpdate(Integer... frame) { drawableName = "rm" + frame[0]; int res_id = getResources().getIdentifier(drawableName, "drawable", getPackageName()); rabbitFrame.setBackgroundResource(res_id); } } 

И запустите его на WindowsFocusChanged

 public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) new DrawRabbit().execute((Void)null) ; else running = false; Log.d(TAG,"onFocusChanged"); } 

Надеюсь, это поможет кому-то!

Вы можете попытаться уменьшить размер изображения. В моем случае это сработало.

 int[] frames = {R.drawable.frame1, R.drawable.frame2, R.drawable.frame3}; AnimationDrawable drawable = new AnimationDrawable(); for (int fr : frames) { Bitmap sample = BitmapFactory.decodeResource(mActivity.getResources(), fr); sample = Bitmap.createScaledBitmap(sample, sample.getWidth()/4, sample.getHeight()/4, false); drawable.addFrame(new BitmapDrawable(mActivity.getResources(), sample), 30); } 

Просто добавьте "android: largeHeap =" true "" в тег приложения android manifest! 🙂

Добавьте эти две строки в файл android манифеста android: hardwareAccelerated = "true" и android: largeHeap = "true"

 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xxx.yyy" > <application android:allowBackup="false" android:fullBackupContent="false" android:hardwareAccelerated="true" android:largeHeap="true"> </application> 

Надеюсь, это вам поможет.