I have a pretty simple activity:
public class SurvivalActivity extends Activity { private static final String KEY_LAYOUT_ID = "SurvivalLayoutId"; int mLayoutId; private static final int[] mSurvivalLayouts = { R.layout.survival1, R.layout.survival2, R.layout.survival3, }; @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Intent i = getIntent(); if (savedInstanceState != null && savedInstanceState.containsKey(KEY_LAYOUT_ID)) { mLayoutId = savedInstanceState.getInt(KEY_LAYOUT_ID, 0); } else if (i != null) { mLayoutId = i.getIntExtra(KEY_LAYOUT_ID, 0); } else { mLayoutId = 0; }
Two static util methods. * just change the font of the TextView
.
All 3 layouts are pretty simple, let me show you the first one:
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <TextView style="@style/Title" android:text="@string/surv1_title" /> <TextView style="@style/Content" android:text="@string/surv1_1" /> <ImageView style="@style/Picture" android:src="@drawable/surv_crafting" /> <TextView style="@style/PicLegend" android:src="@string/surv_crafting_leg" /> <ImageView style="@style/Picture" android:src="@drawable/surv_hache" /> <TextView style="@style/PicLegend" android:src="@string/surv_hache_leg" /> <ImageView style="@style/Picture" android:src="@drawable/surv_pioche" /> <TextView style="@style/PicLegend" android:src="@string/surv_pioche_leg" /> <TextView style="@style/Content" android:text="@string/surv1_2" /> <ImageView style="@style/Picture" android:src="@drawable/surv_charbon" /> <TextView style="@style/PicLegend" android:src="@string/surv_charbon_leg" /> <TextView style="@style/Content" android:text="@string/surv1_3" /> <ImageView style="@style/Picture" android:src="@drawable/surv_torch" /> <TextView style="@style/PicLegend" android:src="@string/surv_torch_leg" /> <TextView style="@style/Content" android:text="@string/surv1_4" /> <ImageView style="@style/Picture" android:src="@drawable/surv_abri" /> <TextView style="@style/PicLegend" android:src="@string/surv_abri_leg" /> <TextView style="@style/Content" android:text="@string/surv1_5" /> <Button style="@style/SurvivalBoxNext" android:text="@string/surv1_next" /> </LinearLayout> </ScrollView>
As you can see, there are several TextView
with ImageView
s and a Button
that start loading the next action.
I run the application, it displays the first screen. I scroll down to the button, click, the second screen is displayed (with hiccups). I scroll down to the button, click and arrow.
03-02 16:36:46.488 E/AndroidRuntime(10611): java.lang.RuntimeException: Unable to start activity ComponentInfo{net.bicou.myapp/net.bicou.myapp.SurvivalActivity}: android.view.InflateException: Binary XML file line
I do not understand:
- Why the previous actions are not freed in order to free some space.
- Why is my application taking up so much heap (
Grow heap (frag case) to 60.869MB for 3600016-byte allocation
) - How to do to consistently display 3 actions containing about 10
TextView
and 10 ImageView
s - If I did something wrong, because I do not see anything wrong with my code, but obviously something is wrong.
Thanks.
Edit: image dimensions of the first action:
-rw-r--r-- 1 bicou staff 167197 29 fév 16:42 surv_abri.jpg 600x377 px -rw-r--r-- 1 bicou staff 24658 29 fév 16:42 surv_charbon.png 559x277 px -rw-r--r-- 1 bicou staff 5285 29 fév 16:42 surv_crafting.png 214x121 px -rw-r--r-- 1 bicou staff 4190 29 fév 16:42 surv_hache.png 214x121 px -rw-r--r-- 1 bicou staff 3809 29 fév 16:42 surv_pioche.png 214x121 px -rw-r--r-- 1 bicou staff 2252 29 fév 16:42 surv_torch.png 215x121 px
Second action:
-rw-r--r-- 1 bicou staff 3371 29 fév 16:42 surv_four.png 204x112 px -rw-r--r-- 1 bicou staff 5059 29 fév 16:42 surv_glass.png 215x122 px -rw-r--r-- 1 bicou staff 3176 29 fév 16:42 surv_malle.png 204x112 px -rw-r--r-- 1 bicou staff 2676 29 fév 16:42 surv_pelle.png 204x112 px -rw-r--r-- 1 bicou staff 167166 29 fév 16:42 surv_repere.png 528x331 px -rw-r--r-- 1 bicou staff 134706 29 fév 16:42 surv_sand.jpg 854x480 px
Third action (failure):
-rw-r--r-- 1 bicou staff 58919 29 fév 16:42 surv_1.jpg 600x377 px -rw-r--r-- 1 bicou staff 51144 29 fév 16:42 surv_2.jpg 600x377 px -rw-r--r-- 1 bicou staff 46917 29 fév 16:42 surv_3.jpg 600x377 px -rw-r--r-- 1 bicou staff 53226 29 fév 16:42 surv_4.jpg 600x377 px -rw-r--r-- 1 bicou staff 37787 29 fév 16:42 surv_5.jpg 600x377 px -rw-r--r-- 1 bicou staff 31050 29 fév 16:42 surv_6.jpg 600x377 px -rw-r--r-- 1 bicou staff 38389 29 fév 16:42 surv_7.jpg 600x377 px -rw-r--r-- 1 bicou staff 44471 29 fév 16:42 surv_8.jpg 600x377 px
And the background "Window":
-rw-r--r-- 1 bicou staff 30857 29 fév 16:42 background_img.png
EDIT:
OK. I tried to inflate the views directly from the code to see if I have an error. Here is my activity code (only + onCreate
variables since the rest are identical)
private static final int[] mTitles = { R.string.surv1_title, R.string.surv2_title, R.string.surv3_title }; private static final int[][] mTextViews = { { R.string.surv1_1, R.string.surv1_2, R.string.surv1_3, R.string.surv1_4, R.string.surv1_5 }, { R.string.surv2_1, R.string.surv2_2, R.string.surv2_3, R.string.surv2_4, R.string.surv2_5, R.string.surv2_6 }, { R.string.surv3_1, R.string.surv3_2, R.string.surv3_3 } }; private static final int[][] mImageViews = { { R.drawable.surv_pioche, R.drawable.surv_crafting, R.drawable.surv_hache, R.drawable.surv_charbon, R.drawable.surv_torch, R.drawable.surv_abri }, { R.drawable.surv_malle, R.drawable.surv_four, R.drawable.surv_pelle, R.drawable.surv_repere, R.drawable.surv_sand, R.drawable.surv_glass }, { R.drawable.surv_1, R.drawable.surv_2, R.drawable.surv_3, R.drawable.surv_4, R.drawable.surv_5, R.drawable.surv_6, R.drawable.surv_7, R.drawable.surv_8 }, }; private static final int[] mNextButtons = { R.string.surv1_next, R.string.surv2_next, R.string.surv3_next }; @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Intent i = getIntent(); if (savedInstanceState != null && savedInstanceState.containsKey(KEY_LAYOUT_ID)) { mLayoutId = savedInstanceState.getInt(KEY_LAYOUT_ID, 0); } else if (i != null) { mLayoutId = i.getIntExtra(KEY_LAYOUT_ID, 0); } else { mLayoutId = 0; }
As you can see, I am simply inflating the views directly, and Li
(which is the alias of Log.i(TAG, ...)
) indicates what was the last ImageView inflated before any failure.
I launched the application, saw the 1st activity, then the second, and, as before, it crashes when the third one loads. The last identifier I saw in logcat was the last image of R.drawable.surv_8
. This is a file with a diagonal of 630x377, 45 kiB.
I tried to change the viewing order as follows:
private static final int[][] mImageViews = { { R.drawable.surv_pioche, R.drawable.surv_crafting, R.drawable.surv_hache, R.drawable.surv_charbon, R.drawable.surv_torch, R.drawable.surv_abri }, { R.drawable.surv_malle, R.drawable.surv_four, R.drawable.surv_pelle, R.drawable.surv_repere, R.drawable.surv_sand, R.drawable.surv_glass }, { R.drawable.surv_8, R.drawable.surv_1, R.drawable.surv_2, R.drawable.surv_3, R.drawable.surv_4, R.drawable.surv_5, R.drawable.surv_6, R.drawable.surv_7, }, };
So, to go forward_8. The app still crashes in the last snapshot, which is R.drawable.surv_7
. So this is not a problem with the image.
Then I deleted one of the images from mImageViews[2]
so that I had only 7 images instead of 8. The application works as expected: the activity loads, when I click the button, I go to the next one, and I go to the first one. Without crashing.
However, I can say that actions 1 and 2 remain in memory. Indeed, look at the timings:
03-04 15:47:13.685 I/ActivityManager(17430): Displayed net.bicou.myapp/.SurvivalActivity: +2s570ms 03-04 15:47:36.834 I/ActivityManager(17430): Displayed net.bicou.myapp/.SurvivalActivity: +803ms 03-04 15:47:39.756 I/ActivityManager(17430): Displayed net.bicou.myapp/.SurvivalActivity: +1s476ms 03-04 15:47:44.201 I/ActivityManager(17430): Displayed net.bicou.myapp/.SurvivalActivity: +462ms 03-04 15:47:46.717 I/ActivityManager(17430): Displayed net.bicou.myapp/.SurvivalActivity: +474ms 03-04 15:47:48.599 I/ActivityManager(17430): Displayed net.bicou.myapp/.SurvivalActivity: +474ms
400 ms instead of 1.5-2.5 s to load activity.
Why does this remain in my memory?
=> ** Do I need to manually take all the pictures with onDestroy()
? **
=> What do you think about this: http://androidactivity.wordpress.com/2011/09/24/solution-for-outofmemoryerror-bitmap-size-exceeds-vm-budget/
With this solution, could I upload as many as 10 bitmaps around the world, and would I release them when I load another activity?