动画Drawable在Android中第二次运行时导致OutOfMemoryError

时间:2012-01-31 15:30:36

标签: android android-layout android-animation

我正在开发游戏,我正在尝试使用一个AnimationDrawable在我的主菜单中显示一个动画。当我运行一次游戏时,它完美运行。但是如果我点击后退按钮,当我再次打开游戏时它会给我OutOfMemorryError。 如果我回到家并回到游戏中,它会加载但不显示动画,它应该是空的。

我认为当它再次打开游戏时它会尝试加载动画,但它已经从之前的运行中加载了,我可以以某种方式释放该内存吗?我该怎么处理这个例外?

搜索我可以发现它是Android中的常见问题,但我找不到任何有用的东西。

如果它是相关的,我的图像是310x316,我有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解决了我的问题。现在我继续在onProgressUpdate()上更改ImageView的背景。可能不是最好的方法,但现在我没有任何问题!这是我的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);
         }   
     }

5 个答案:

答案 0 :(得分:22)

当您退出此屏幕时,您需要释放位图使用的内存。不幸的是,对于Android的早期版本(afaik这是&#34;修复&#34;自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);
    
  3. 我希望它会帮助你。

答案 1 :(得分:3)

所以,我设法通过这种方法解决了我的问题:

为绘图创建了一个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);
       }   
   }

并在WindowsFocusChanged

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

希望它有所帮助!

答案 2 :(得分:1)

您可以尝试缩小图像尺寸。我的情况很有效。

>>> print("{0}{0:27}{0:39}{0:51}\n{4}".format("Word", "Occurence", "Avg. Score", "Std. Dev.", "="*51))
WordWord                       Word                                   Word

===================================================

答案 3 :(得分:1)

只需添加&#34; android:largeHeap =&#34; true&#34;&#34;在应用程序标签android清单! :)

答案 4 :(得分:1)

在Android清单文件android中添加这两行:hardwareAccelerated =&#34; true&#34;和android:largeHeap =&#34; true&#34;

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

希望能帮助你。