2015-11-30 26 views
1

我有4个图像序列(png格式),我需要为我的动画使用。每个序列大约50帧长,每帧大约300x300,所以我有30 MB的资源加载。什么是加载它们以避免内存泄漏的最有效方式?我应该去寻找xml可绘制动画还是有更好的方法?为动画加载大型图像序列的有效方法

我不需要同时在屏幕上显示它们。只显示一个动画。

回答

0

也许是有点迟了:)但我希望这可以帮助其他用户。 最后,我用一个简单的循环来解决它,它加载一个图像,绘制并摧毁它。

 int frames = 50; 

     //LOADING-REMOVING NEEDED FRAMES 
     //set animation range 
     i = currentFrame % frames; 
     //frame to cache 
     frameList.add(BitmapsLoader(i)); //custom function to load a specified frame from res 
     if (frameList.size() == 3) { 
      //frame to draw 
      canvas.drawBitmap(frameList.get(1), left, top, null); 
      //frame to remove 
      frameList.get(0).recycle(); 
      frameList.remove(0); 
     } 

这会保持内存分配稳定,无论您的动画有多少帧。很明显,它在CPU上花费更多,因为我们不是预先加载所有资源,而是在每一帧中继续加载它们。尽管有这些事实,我的应用程序运行平稳。 在三星Galaxy S3和Galaxy Tab 4上测试。

+0

你能否详细说明你的答案?你有没有对AnimationDrawable类进行分类,或者你是否以自己的方式实现了它?这是在一个OnDraw方法吗?我真的想尝试你的方法,请分享更多的解决方案... –

0

非常感谢。 我面临着同样的问题,在看到你的答案一段时间后,我通过覆盖AnimationDrawable来解决它。 因此,如果问题在于你无法加载阵列中的所有图像,因为它对于内存来说太大了,所以在你需要的时候加载图像。 我AnimationDrawable是这样的:

public abstract class MyAnimationDrawable extends AnimationDrawable { 

    private Context context; 
    private int current; 
    private int reqWidth; 
    private int reqHeight; 
    private int totalTime; 

    public MyAnimationDrawable(Context context, int reqWidth, int reqHeight) { 
     this.context = context; 
     this.current = 0; 
     //In my case size of screen to scale Drawable 
     this.reqWidth = reqWidth; 
     this.reqHeight = reqHeight; 
     this.totalTime = 0; 
    } 

    @Override 
    public void addFrame(Drawable frame, int duration) { 
     super.addFrame(frame, duration); 
     totalTime += duration; 
    } 

    @Override 
    public void start() { 
     super.start(); 
     new Handler().postDelayed(new Runnable() { 

      public void run() { 
       onAnimationFinish(); 
      } 
     }, totalTime); 
    } 

    public int getTotalTime() { 
     return totalTime; 
    } 

    @Override 
    public void draw(Canvas canvas) { 
     try { 
      //Loading image from assets, you could make it from resources 
      Bitmap bmp = BitmapFactory.decodeStream(context.getAssets().open("presentation/intro_000"+(current < 10 ? "0"+current : current)+".jpg")); 
      //Scaling image to fitCenter 
      Matrix m = new Matrix(); 
      m.setRectToRect(new RectF(0, 0, bmp.getWidth(), bmp.getHeight()), new RectF(0, 0, reqWidth, reqHeight), Matrix.ScaleToFit.CENTER); 
      bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), m, true); 
      //Calculating the start 'x' and 'y' to paint the Bitmap 
      int x = (reqWidth - bmp.getWidth())/2; 
      int y = (reqHeight - bmp.getHeight())/2; 
      //Painting Bitmap in canvas 
      canvas.drawBitmap(bmp, x, y, null); 
      //Jump to next item 
      current++; 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    abstract void onAnimationFinish(); 

} 

玩到现在,你需要做的动画下一步

//Get your ImageView 
    View image = MainActivity.this.findViewById(R.id.presentation); 

    //Create AnimationDrawable 
    final AnimationDrawable animation = new MyAnimationDrawable(this, displayMetrics.widthPixels, displayMetrics.heightPixels) { 

     @Override 
     void onAnimationFinish() { 
      //Do something when finish animation 
     } 

    }; 
    animation.setOneShot(true); //dont repeat animation 
    //This is just to say that my AnimationDrawable has 72 frames with 50 milliseconds interval 
    try { 
     //Always load same bitmap, anyway you load the right one in draw() method in MyAnimationDrawable 
     Bitmap bmp = BitmapFactory.decodeStream(MainActivity.this.getAssets().open("presentation/intro_00000.jpg")); 
     for (int i = 0; i < 72; i++) { 
      animation.addFrame(new BitmapDrawable(getResources(), bmp), 50); 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    //Set AnimationDrawable to ImageView 
    if (Build.VERSION.SDK_INT < 16) { 
     image.setBackgroundDrawable(animation); 
    } else { 
     image.setBackground(animation); 
    } 

    //Start animation 
    image.post(new Runnable() { 

     @Override 
     public void run() { 
      animation.start(); 
     } 

    }); 

这是所有和工程确定形成我!