Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Android

Janine Suvak
Janine Suvak
14,954 Points

out of memory error with animations

I've run into an out-of-memory problem using a simple animation like the crystal ball one, only adding another similar animation in a subsequent activity. Individually, each activity animation works fine. Putting both animations onto one activity also results in the out of memory error. From what I've found it may be a native android image/memory-handling bug that is discussed in the following link: http://stackoverflow.com/questions/477572/strange-out-of-memory-issue-while-loading-an-image-to-a-bitmap-object

And also related image/memory management discussion here: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

But I just can't make that leap of implementing this to the images in the crystal ball animation loop.

Any suggestions?

4 Answers

I understand your description of the problem, but it would be helpful to me if you could post your code. Using too many images will be able to take down your application with a memory error. I've had it when I wanted to use 6 huge pictures at once. Lowering the resolution worked for me. Nonetheless, code would be helpful. Thanks!

Janine Suvak
Janine Suvak
14,954 Points

Hi Ernest,

Yep, I'm running into the same problem with another app that doesn't have the frame animation but it does have a number of images, so it's hanging up from one activity to the next now that I'm plugging in background images. But it's in the same place - going from one activity to the next. Each activity works fine when uncoupled.

I'm not sure what code you want to see that might be helpful. The animation is just like in crystal ball, with about 42 frames of .png images. Each of these is 21KB. Plus the animation file.

In a second, simpler (without animation) app I'm running into the same thing as I add the artwork. In this case, an activity with nine ImageButtons and background image where any of the buttons goes to the next activity with five ImageButtons and a background image.

The background images are in the respective xml files: android:src="@drawable/background4" for an ImageView or other images in ImageButtons. I tried to use images that were the right size; I could make them smaller but it seems that then you get into image quality issues and in general, I think this is possibly delaying the inevitable?

From the android developer docs I was thinking that dumping the images in onStop(); would keep them from piling up, but I'm not sure of the syntax.

[http://developer.android.com/training/basics/activity-lifecycle/stopping.html When your activity receives a call to the onStop() method, it's no longer visible and should release almost all resources that aren't needed while the user is not using it. Once your activity is stopped, the system might destroy the instance if it needs to recover system memory. In extreme cases, the system might simply kill your app process without calling the activity's final onDestroy() callback, so it's important you use onStop() to release resources that might leak memory.]

The stackoverflow link in my original post refers to Bitmap images, which I've learned are the PNG or JPG images and I see Bitmap factory comments in the LogCat, and it has code to optimally scale images, but I don't understand how to implement it.

I have a feeling the solution is somewhere in the vicinity of right in front of my face.

Thanks!

Hey Janine,

I'm going to see if Ben Jakuben might have any tips for you. I'm away right now, so I can't look too deep into the problem you're having, mostly because I never had to use an animation before that little tutorial from treehouse. Secondly, try watching this "Dev Byte" on Bitmap allocation. https://www.youtube.com/watch?v=rsQet4nBVi8

Ben Jakuben
Ben Jakuben
Treehouse Teacher

I wish I could help! Animation in Android can be a real pain. When writing the Crystal Ball app I had to work around some of these same issues, which is why we have such low-res images for the Crystal Ball. I doubt this will help, but would it be possible to embed the animation as a movie instead? I thought about that for the Crystal Ball but we couldn't do it because there was a black frame or something at either the beginning or end of the sequence (I don't remember exactly). Wish I could be of more help...

Janine Suvak
Janine Suvak
14,954 Points

Yep, now I know why a buddy of mine called me a masochist when I asked him the same question. Coming from the iOS world, how was I to know? :) Definitely appreciate the help and the embedded movie suggestion. I patched it up enough in time for the demo/media event but will probably go with Unity for final product. Thanks again!

Just to share the love, this was a project for a local school for special needs kids: http://gulfnews.com/news/gulf/uae/education/special-tailor-made-apps-for-al-noor-training-centre-1.1198268 So heartwarming to see how much they enjoyed the apps! :)

And one more time - THANK YOU BEN AND TREEHOUSE! Started my first day of Android development with your tutorial on Apr 26 and was able to get this done for the kids. Woo!

Awesome! Congrats!

Ben Jakuben
Ben Jakuben
Treehouse Teacher

Wow Janine, that's amazing! What a great project! Our business teacher, Pasan Premaratne, is from Dubai. He'll enjoy hearing about this, too. :smile:

I'm so glad Treehouse could be of help to you!

Pasan Premaratne
Pasan Premaratne
Treehouse Teacher

Janine Suvak

This is quite awesome! Keep up the great work :)

Janine Suvak
Janine Suvak
14,954 Points

Ok I watched the video and recreated the sample app using the crystal ball animation images. This is only good for images that are the same size, but that's ok for these animation frames. Without the box checked, I got up to 38 msec load time, while with it the longest I got was 18, a significant percentage difference. So I see that this is helping as advertised, but still don't see how to apply this to the animation as it runs through the array of images.

I'll keep poking at it but in the meantime here's the code:

package com.example.bitmapstuff;

import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.widget.CheckBox; import android.widget.ImageView; import android.widget.TextView;

public class MainActivity extends Activity {

int mCurrentIndex = 0;
Bitmap mCurrentBitmap = null;
BitmapFactory.Options mBitmapOptions;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final int[] imageIDs = {R.drawable.ball01, R.drawable.ball02, R.drawable.ball03, R.drawable.ball04, 
                            R.drawable.ball05, R.drawable.ball06, R.drawable.ball07, R.drawable.ball08,
                            R.drawable.ball09, R.drawable.ball10, R.drawable.ball11, R.drawable.ball12, 
                            R.drawable.ball13, R.drawable.ball14, R.drawable.ball15, R.drawable.ball16,
                            R.drawable.ball17, R.drawable.ball18, R.drawable.ball17, R.drawable.ball18, 
                            R.drawable.ball21, R.drawable.ball22, R.drawable.ball23, R.drawable.ball24                              
    };

    final CheckBox checkbox = (CheckBox) findViewById(R.id.checkbox);
    final TextView durationTextview = (TextView) findViewById(R.id.loadDuration);
    final ImageView imageview = (ImageView) findViewById(R.id.imageview);

    mBitmapOptions = new BitmapFactory.Options();
    mBitmapOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(getResources(), R.drawable.ball01, mBitmapOptions);
    mCurrentBitmap = Bitmap.createBitmap(mBitmapOptions.outWidth, mBitmapOptions.outHeight, Bitmap.Config.ARGB_8888);
    mBitmapOptions.inJustDecodeBounds = false;
    mBitmapOptions.inBitmap = mCurrentBitmap;
    mBitmapOptions.inSampleSize = 1;
    BitmapFactory.decodeResource(getResources(), R.drawable.ball01, mBitmapOptions);
    imageview.setImageBitmap(mCurrentBitmap);

    imageview.setOnClickListener(new View.OnClickListener() {
        @Override 
        public void onClick(View v) {
            mCurrentIndex = (mCurrentIndex + 1) % imageIDs.length;
            BitmapFactory.Options bitmapOptions = null;
            if (checkbox.isChecked()) {
                bitmapOptions = mBitmapOptions;
                bitmapOptions.inBitmap = mCurrentBitmap;
            }
            long startTime = System.currentTimeMillis();
            mCurrentBitmap = BitmapFactory.decodeResource(getResources(), imageIDs[mCurrentIndex], bitmapOptions);
            imageview.setImageBitmap(mCurrentBitmap);
            durationTextview.setText("Load took "+ (System.currentTimeMillis() - startTime));
        }
    });
}

}

xml: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" >

<TextView
    android:id="@+id/loadDuration"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world" />

<CheckBox
    android:id="@+id/checkbox"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignBaseline="@+id/loadDuration"
    android:layout_alignBottom="@+id/loadDuration"
    android:layout_alignParentRight="true"
    android:text="CheckBox" />

<ImageView
    android:id="@+id/imageview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:src="@drawable/ball01"
    android:contentDescription="crystal ball" />

</RelativeLayout>