2

I get out of memory exceptions when loading images into my app. I integrated Picasso to load images, but the code below is not working with an animation-list for an AnimationDrawable. The animation is null:

Picasso.with(this).load(R.drawable.qtidle).into(qtSelectButton);
qtIdleAnimation = (AnimationDrawable)qtSelectButton.getDrawable();
if (qtIdleAnimation != null)
    qtIdleAnimation.start();

The AnimationDrawable works, if I use this code without Picasso:

qtIdleAnimation = new AnimationDrawable();
qtIdleAnimation.setOneShot(false);
for (int i = 1; i <= 7; i++) {
    int qtidleId = res.getIdentifier("qtidle" + i, "drawable", this.getPackageName());
    qtIdleAnimation.addFrame(res.getDrawable(qtidleId), 100);
}
qtSelectButton.setImageDrawable(qtIdleAnimation);
if (qtIdleAnimation != null)
    qtIdleAnimation.start();

But this code causes the out of memory exceptions. Is it possible at all to load animation-lists with Picasso?

Christian
  • 317
  • 1
  • 14

1 Answers1

1

Picasso can't directly load an animation-list defined in an xml file into a View. But it is not too difficult to mimic the basic behavior of Picasso yourself:

1. Define and start the animation programmatically, like you did, but inside an AsyncTask to avoid out-of-memory exceptions

Resources res = this.getResources();
ImageView imageView = findViewById(R.id.image_view);
int[] ids = new int[] {R.drawable.img1, R.drawable.img2, R.drawable.img3};

Create a sublcass of AsyncTask:

private class LoadAnimationTask extends AsyncTask<Void, Void, AnimationDrawable> {
    @Override
    protected AnimationDrawable doInBackground(Void... voids) {
        // Runs in the background and doesn't block the UI thread
        AnimationDrawable a = new AnimationDrawable();
        for (int id : ids) {
            a.addFrame(res.getDrawable(id), 100);
        }
        return a;
    }
    @Override
    protected void onPostExecute(AnimationDrawable a) {
        // This will run once 'doInBackground' has finished
        imageView.setImageDrawable(a);
        if (a != null)
            a.start();
    }
}

Then run the task to load the animation into your ImageView:

new LoadAnimationTask().execute()

2. If your drawables are larger than your view, save memory by only loading the drawables at the required resolution

Instead of adding the drawable directly:

a.addFrame(res.getDrawable(id), 100);

Add a scaled-down version of it:

a.addFrame(new BitmapDrawable(res, decodeSampledBitmapFromResource(res, id, w, h));

where w and h are your view's dimensions, and decodeSampledBitmapFromResource() is a method defined in the Android official documentation (Loading Large Bitmaps Efficiently)

Josselin
  • 2,593
  • 2
  • 22
  • 35