cristi.gherghina
cristi.gherghina

Reputation: 321

How to reduce memory usage in Android?

I want to display some random images from my drawable folder when I press a button.

I named my photos "img_0"...to "img_51"

This is what I tried :

ImageView card1, card2, card3, card4, card5;
Button bPlay;

ArrayList<Integer> numbers = new ArrayList<Integer>();
Random randomGenerator = new Random();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);

    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

    setContentView(R.layout.activity_play);

    setReferences();
}


private void setReferences() {
    card1 = (ImageView) findViewById(R.id.card1);
    card2 = (ImageView) findViewById(R.id.card2);
    card3 = (ImageView) findViewById(R.id.card3);
    card4 = (ImageView) findViewById(R.id.card4);
    card5 = (ImageView) findViewById(R.id.card5);
    bPlay = (Button) findViewById(R.id.bPlay2);
    bPlay.setOnClickListener(this);
}

private void getRandomNumbers() {
    while(numbers.size() < 5) {
        int random = randomGenerator .nextInt(51);
        if (!numbers.contains(random)) {
            numbers.add(random);
        }
    }
}

private void clearArrayList() {
    for(int i = numbers.size()-1 ; i >= 0; i--){
        numbers.remove(numbers.get(i));
    }
}

private void setBitmap(ImageView iv, int n) {
    String str = "img_" + numbers.get(n);

    int resID = getResources().getIdentifier(str, "drawable",  getPackageName());
    iv.setImageResource(resID);
}

@Override
public void onClick(View v) {
    getRandomNumbers();

    setBitmap(card1, 0);
    setBitmap(card2, 1);
    setBitmap(card3, 2);
    setBitmap(card4, 3);
    setBitmap(card5, 4);

    clearArrayList();
}

I was looking in the memory tab from the emulator, and I saw that the memory is very highly used...

How can I reduce the memory usage? only when I press one time the button it has 70 and something in the VM HEAP.

Any idea is very welcomed !

I tried also with Bitmap and recycle but it gives me error.. Application has stopped working...

Here is what i tried :

private void setBitmap(ImageView iv, int n) {
        String str = "img_" + numbers.get(n);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), getResourceID(str, "drawable",
                this));
        iv.setImageBitmap(bitmap);
        bitmap.recycle();
    }

Here is the logcat :

    07-10 16:57:10.402    1906-1906/? I/art﹕ Not late-enabling -Xcheck:jni (already on)
07-10 16:57:14.321    1906-1937/com.symplyfyweb.gherghina.oldschoolwesternpoker D/OpenGLRenderer﹕ Use EGL_SWAP_BEHAVIOR_PRESERVED: true
07-10 16:57:14.335    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker D/﹕ HostConnection::get() New Host Connection established 0xb4a93f40, tid 1906
07-10 16:57:14.349    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker D/Atlas﹕ Validating map...
07-10 16:57:14.813    1906-1937/com.symplyfyweb.gherghina.oldschoolwesternpoker D/﹕ HostConnection::get() New Host Connection established 0xb4b270b0, tid 1937
07-10 16:57:14.957    1906-1937/com.symplyfyweb.gherghina.oldschoolwesternpoker I/OpenGLRenderer﹕ Initialized EGL, version 1.4
07-10 16:57:15.032    1906-1937/com.symplyfyweb.gherghina.oldschoolwesternpoker D/OpenGLRenderer﹕ Enabling debug mode 0
07-10 16:57:15.054    1906-1937/com.symplyfyweb.gherghina.oldschoolwesternpoker W/EGL_emulation﹕ eglSurfaceAttrib not implemented
07-10 16:57:15.063    1906-1937/com.symplyfyweb.gherghina.oldschoolwesternpoker W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0xb4b23b00, error=EGL_SUCCESS
07-10 16:57:15.169    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/Choreographer﹕ Skipped 38 frames!  The application may be doing too much work on its main thread.
07-10 16:57:16.748    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/Choreographer﹕ Skipped 93 frames!  The application may be doing too much work on its main thread.
07-10 16:57:22.533    1906-1937/com.symplyfyweb.gherghina.oldschoolwesternpoker W/EGL_emulation﹕ eglSurfaceAttrib not implemented
07-10 16:57:22.533    1906-1937/com.symplyfyweb.gherghina.oldschoolwesternpoker W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0xb4b23cc0, error=EGL_SUCCESS
07-10 16:57:23.378    1906-1913/com.symplyfyweb.gherghina.oldschoolwesternpoker W/art﹕ Suspending all threads took: 19.779ms
07-10 16:57:28.898    1906-1913/com.symplyfyweb.gherghina.oldschoolwesternpoker W/art﹕ Suspending all threads took: 12.510ms
07-10 16:57:31.940    1906-1918/com.symplyfyweb.gherghina.oldschoolwesternpoker I/art﹕ Clamp target GC heap from 66MB to 64MB
07-10 16:57:32.352    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/art﹕ Alloc sticky concurrent mark sweep GC freed 8(432B) AllocSpace objects, 0(0B) LOS objects, 1% free, 62MB/64MB, paused 1.468ms total 17.160ms
07-10 16:57:32.378    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/art﹕ Clamp target GC heap from 66MB to 64MB
07-10 16:57:32.378    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/art﹕ Alloc partial concurrent mark sweep GC freed 14(576B) AllocSpace objects, 0(0B) LOS objects, 1% free, 62MB/64MB, paused 889us total 19.090ms
07-10 16:57:32.444    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/art﹕ Clamp target GC heap from 66MB to 64MB
07-10 16:57:32.444    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/art﹕ Alloc concurrent mark sweep GC freed 8(12KB) AllocSpace objects, 0(0B) LOS objects, 1% free, 62MB/64MB, paused 789us total 57.650ms
07-10 16:57:32.451    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/art﹕ Forcing collection of SoftReferences for 12MB allocation
07-10 16:57:32.501    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/art﹕ Clamp target GC heap from 66MB to 64MB
07-10 16:57:32.502    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/art﹕ Alloc concurrent mark sweep GC freed 11(288B) AllocSpace objects, 0(0B) LOS objects, 1% free, 62MB/64MB, paused 799us total 49.442ms
07-10 16:57:32.507    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker E/art﹕ Throwing OutOfMemoryError "Failed to allocate a 13068012 byte allocation with 1263808 free bytes and 1234KB until OOM"
07-10 16:57:32.524    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/art﹕ Alloc sticky concurrent mark sweep GC freed 5(448B) AllocSpace objects, 0(0B) LOS objects, 1% free, 62MB/64MB, paused 731us total 14.526ms
07-10 16:57:32.550    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/art﹕ Clamp target GC heap from 66MB to 64MB
07-10 16:57:32.551    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/art﹕ Alloc partial concurrent mark sweep GC freed 10(376B) AllocSpace objects, 0(0B) LOS objects, 1% free, 62MB/64MB, paused 954us total 19.113ms
07-10 16:57:32.664    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/art﹕ Clamp target GC heap from 66MB to 64MB
07-10 16:57:32.665    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/art﹕ Alloc concurrent mark sweep GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 1% free, 62MB/64MB, paused 1.193ms total 108.749ms
07-10 16:57:32.675    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker W/art﹕ Suspending all threads took: 9.507ms
07-10 16:57:32.675    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/art﹕ Forcing collection of SoftReferences for 12MB allocation
07-10 16:57:32.770    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/art﹕ Clamp target GC heap from 66MB to 64MB
07-10 16:57:32.770    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker I/art﹕ Alloc concurrent mark sweep GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 1% free, 62MB/64MB, paused 11.517ms total 93.336ms
07-10 16:57:32.775    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker E/art﹕ Throwing OutOfMemoryError "Failed to allocate a 13068012 byte allocation with 1263992 free bytes and 1234KB until OOM"
07-10 16:57:32.777    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker D/skia﹕ --- allocation failed for scaled bitmap
07-10 16:57:32.779    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker D/AndroidRuntime﹕ Shutting down VM
    --------- beginning of crash
07-10 16:57:32.802    1906-1906/com.symplyfyweb.gherghina.oldschoolwesternpoker E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.symplyfyweb.gherghina.oldschoolwesternpoker, PID: 1906
    java.lang.OutOfMemoryError: Failed to allocate a 13068012 byte allocation with 1263992 free bytes and 1234KB until OOM
            at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
            at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
            at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:609)
            at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444)
            at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:467)
            at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:497)
            at com.symplyfyweb.gherghina.oldschoolwesternpoker.PlayActivity.setBitmap(PlayActivity.java:97)
            at com.symplyfyweb.gherghina.oldschoolwesternpoker.PlayActivity.onClick(PlayActivity.java:112)
            at android.view.View.performClick(View.java:4780)
            at android.view.View$PerformClick.run(View.java:19866)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5257)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

Upvotes: 0

Views: 1424

Answers (3)

neonDion
neonDion

Reputation: 2358

Besides recycling bitmaps, one thing that can really help is to not load a full size bitmap if you don't need it. For instance, if you are trying to load images that were taken using the device camera, they probably have a much higher resolution than you are able to show on your display anyway (for example, the full size image may be 2000 x 20000 pixels and you may be trying to display it in an ImageView that is 500 x 500 pixels). The full size bitmap will take up a lot more room in memory and in reality you will be discarding a lot of the pixels when showing on a reduced size imageview.

Try this SO post to learn how to reduce the memory footprint of a bitmap if the ImageView it will be displayed in isn't as big as the full-size image:

How to scale bitmap to screen size?

Upvotes: 0

krystian71115
krystian71115

Reputation: 1937

// create second array list: 
ArrayList<Bitmap> bitmaps = new ArrayList<Bitmap>();
private void clearArrayList() {
    numbers.clear();
    for(Bitmap bitmap : bitmaps)
    {
        bitmap.recycle();
    }
    bitmaps.clear();
}

@Override
public void onClick(View v) {
    clearArrayList();
    getRandomNumbers();

    setBitmap(card1, 0);
    setBitmap(card2, 1);
    setBitmap(card3, 2);
    setBitmap(card4, 3);
    setBitmap(card5, 4);
}

Edit:

private void setBitmap(ImageView iv, int n) {
        String str = "img_" + numbers.get(n);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), getResourceID(str, "drawable",
                this));
        iv.setImageBitmap(bitmap);
        bitmaps.add(bitmap);
    }

Upvotes: 0

Jmrapp
Jmrapp

Reputation: 520

You should really cache your images so that they only need to be loaded one time.

It would be very simple, all you would have to do is when you go to load a bitmap, check to see if it's already in the cache and if it is then use that. If it isn't then load the image. This will prevent you from loading resources multiple times.

HashMap<String, Integer> resCache = new HashMap<String, Integer>();
...
...
private void setBitmap(ImageView iv, int n) {
    String str = "img_" + numbers.get(n);
    int resID = -1;
    if  (resCache.containsKey(str)) {
        resID = resCache.get (str);
    } else {
        resID = getResources().getIdentifier(str, "drawable",  getPackageName());
        resCache.put (str, resID);
    }
    iv.setImageResource(resID);
}

Upvotes: 1

Related Questions