android viewpager out of memory

android, android-viewpager, out-of-memory

Solution

For each imageView you will have to call `recycle()` method. So, before the line:

bild.setImageBitmap(DecodeImage.decode(bild.getContext().getResources(), R.drawable.swipe_bild));

You have to put the line:

((BitmapDrawable) bild.getDrawable()).getBitmap().recycle();

If the problem persists, it's because the image is too large and then you will have to compress it

Problem

first i would like to say that english is not my native language. So please forgive me my mistakes. To my problem: I have a `ViewPager` with 10 pages and tabs. The first window is for setting and the others are questions. You start with the first question and i show an image, if you click "yes" "no" then you go to the next page where the second picture is shown with another question. I get everytime the oom error (as i get to the 7 page). I read some tipps about it i now i use bitmap decoder everytime i bind the image to my `ImageView`. But that dont help much. I still have the same problem. My decoder has `*.inPurgeable = true;` I know there is an option to change your manifest.xml to allow more heap size but i think that will only delay the error. Can someone look through my code please and tell me something that i am doing wrong. Cause it seems to me fine but cause i am new to programming i could have made some big mistakes :) My viewpager with the adapter: ``` public class WaldViewPager extends FragmentActivity implements ActionBar.TabListener { private static AppSectionsPagerAdapter mAppSectionsPagerAdapter; static private ViewPager mViewPager; private static Context context; public static int bitmap; private int width, height; private ViewGroup rootWald; private static int textSize = 0; private Dialog dialog; public static int lastUsed = 1; private static int ergebnis = 0; private static int[] fragenListe = new int[8]; private static int[] antworten = new int[9]; public static void setErgebnis(int zahl){ ergebnis = zahl; } public static int getErgebnis(){ return ergebnis; } public static void setAntwort(int position, int antwort){ antworten[position-1] = antwort; } public static int getAntwort(int position){ return antworten[position-1]; } public static void setPage(int position){ mViewPager.setCurrentItem(position, true); } public static int getPage(){ return mViewPager.getCurrentItem(); } private void resetListe(){ for(int i=0; i<fragenListe.length; i++){ fragenListe[i]=0; } } private void resetAntworten(){ for(int i=0; i<antworten.length; i++){ antworten[i]=0; } } public static boolean getFrage(int position){ if(fragenListe[position-2] == 1){ return true; }else{ return false; } } public static void setPageVisible(int position, boolean status){ if(status == true){ fragenListe[position-2] = 1; }else if(status == false){ fragenListe[position-2] = 0; } } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_viewpager); overridePendingTransition(R.anim.fade_out, R.anim.fade_in); mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getSupportFragmentManager()); WaldViewPager.context = getApplicationContext(); berechneSchriftgroese(); setupHelpInfoDialog(); resetListe(); resetAntworten(); rootWald = (ViewGroup) findViewById(R.id.toast_layout_root); final ActionBar actionBar = getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); actionBar.setLogo(R.drawable.fake); mViewPager = (ViewPager) findViewById(R.id.pager); mViewPager.setAdapter(mAppSectionsPagerAdapter); mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position){ actionBar.getTabAt(position).select(); ViewParent root = findViewById(android.R.id.content).getParent(); findAndUpdateSpinner(root, position); } private boolean findAndUpdateSpinner(Object root, int position){ if (root instanceof android.widget.Spinner){ Spinner spinner = (Spinner) root; spinner.setSelection(position); return true; }else if (root instanceof ViewGroup){ ViewGroup group = (ViewGroup) root; if (group.getId() != android.R.id.content){ for (int i = 0; i < group.getChildCount(); i++){ if (findAndUpdateSpinner(group.getChildAt(i), position)){ return true; } } } } return false; } }); for (int i = 0; i < mAppSectionsPagerAdapter.getCount(); i++) { actionBar.addTab(actionBar.newTab().setText(mAppSectionsPagerAdapter.getPageTitle(i)).setTabListener(this)); } mViewPager.setCurrentItem(1, true); } @Override public void onBackPressed() { if (mViewPager.getCurrentItem() == 1) { super.onBackPressed(); } else { mViewPager.setCurrentItem(1, true); } } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater menuInflater = getMenuInflater(); menuInflater.inflate(R.menu.bottom_bar_frage, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_settings_frage: if(mViewPager.getCurrentItem()==0){ mViewPager.setCurrentItem(lastUsed, true); }else{ lastUsed = mViewPager.getCurrentItem(); mViewPager.setCurrentItem(0, true); } return true; case R.id.menu_info: dialog.show(); return true; default: return super.onOptionsItemSelected(item); } } private void setupHelpInfoDialog(){ dialog = new Dialog(WaldViewPager.this); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.setCancelable(true); dialog.setContentView(R.layout.dialog_info); dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT)); TextView text = (TextView) dialog.findViewById(R.id.dialog_ueberschrift); text.setText("Bedienung der App"); if(MainViewPager.getTextSize()!=0){ text.setTextSize(text.getTextSize()-MainViewPager.getTextSize()); } text = (TextView) dialog.findViewById(R.id.dialog_text1); text.setText("-Wischfunktion:"); if(MainViewPager.getTextSize()!=0){ text.setTextSize(text.getTextSize()-MainViewPager.getTextSize()); } text = (TextView) dialog.findViewById(R.id.dialog_text1_sub); text.setText("Zum Navigieren können Sie entweder auf die Tabs zurückgreifen oder Sie wischen das Fenster links oder rechts"); if(MainViewPager.getTextSize()!=0){ text.setTextSize(text.getTextSize()-MainViewPager.getTextSize()); } text = (TextView) dialog.findViewById(R.id.dialog_text2); text.setText("-Zoomfunktion:"); if(MainViewPager.getTextSize()!=0){ text.setTextSize(text.getTextSize()-MainViewPager.getTextSize()); } text = (TextView) dialog.findViewById(R.id.dialog_text2_sub); text.setText("Wenn Sie auf das Bild klicken, können Sie es mit 2 Fingern vergrößern bzw. verkleinern"); if(MainViewPager.getTextSize()!=0){ text.setTextSize(text.getTextSize()-MainViewPager.getTextSize()); } text = (TextView) dialog.findViewById(R.id.dialog_text3); text.setText("-Erklärungshilfe:"); if(MainViewPager.getTextSize()!=0){ text.setTextSize(text.getTextSize()-MainViewPager.getTextSize()); } text = (TextView) dialog.findViewById(R.id.dialog_text3_sub); text.setMovementMethod(LinkMovementMethod.getInstance()); text.setText(ClickableText.addClickablePart("Damit Sie wenig Zeit beim Suchen der Fremd/Fachwörtern verlieren, können Sie Wörter wie \u200EClypeus\u200E direkt hier nachschlagen", context, rootWald), BufferType.SPANNABLE); if(MainViewPager.getTextSize()!=0){ text.setTextSize(text.getTextSize()-MainViewPager.getTextSize()); } ImageView bild = (ImageView) dialog.findViewById(R.id.dialog_bild1); ImageView bild = (ImageView) dialog.findViewById(R.id.dialog_bild1); bild.setImageBitmap(DecodeImage.decode(bild.getContext().getResources(), R.drawable.swipe)); bild = (ImageView) dialog.findViewById(R.id.dialog_bild2); bild.setImageBitmap(DecodeImage.decode(bild.getContext().getResources(), R.drawable.swipe_bild)); } @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { // TODO Auto-generated method stub mViewPager.setCurrentItem(tab.getPosition(), true); } @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { // TODO Auto-generated method stub } @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { // TODO Auto-generated method stub } ``` AppSectionsPagerAdapter ``` public static class AppSectionsPagerAdapter extends FragmentStatePagerAdapter { public AppSectionsPagerAdapter(FragmentManager fm) { super(fm); } @Override public Parcelable saveState() { return null; } @Override public Fragment getItem(int i) { switch (i) { case 0: return new SettingsFrage(); case 1: return new FrageA(); case 2: return new FrageB(); case 3: return new FrageC(); case 4: return new FrageD(); case 5: return new FrageE(); case 6: return new FrageF(); case 7: return new FrageG(); case 8: return new FrageH(); case 9: return new FrageI(); } return null; } @Override public int getCount() { return 10; } @Override public float getPageWidth(int position) { if(position == 0){ return super.getPageWidth(position)*0.6f; } return super.getPageWidth(position); } @Override public CharSequence getPageTitle(int position) { switch(position){ case 0: return "Settings"; case 1: return "Einkerbung"; case 2: return "Einbuchtung"; case 3: return "Farbe"; case 4: return "Stirndreieck"; case 5: return "Haare"; case 6: return "Beborstung"; case 7: return "Hinterhaupt"; case 8: return "Pigmentierung"; case 9: return "Mesosoma"; } return null; } } public static Context getContext(){ return WaldViewPager.context; } public static int getTextSize(){ return textSize; } private void berechneSchriftgroese(){ Display display = getWindowManager().getDefaultDisplay(); Point size = new Point(); display.getSize(size); width = size.x; height = size.y; if(width<=480 || height<=480){ textSize = 12; } } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); overridePendingTransition(R.anim.fade_out, R.anim.fade_in); } } ``` One of my question: ``` public class FrageB extends Fragment implements OnClickListener{ public static ImageView bild; public static TextView ueberschrift, frage, frageZusatz1, frageZusatz2; public static View viewA, viewB, viewC; public static RadioButton auswahlA, auswahlB, auswahlC; String stringUeberschrift = "Einbuchtung"; String stringFrage = "Welche Form hat der Hinterrand des Kopfes?"; String stringAuswahlA = "keine Delle"; String stringAuswahlB = "Delle"; String stringAuswahlC = "unsicher"; String stringFrageZusatz1 = "keine Delle: nicht oder nur schwach eingebuchtet, keine deutliche Delle"; String stringFrageZusatz2 = "Delle: tief eingebuchtet, deutliche Delle"; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fake_frage, container, false); ViewGroup root = (ViewGroup) v.findViewById(R.id.toast_layout_root); bild = (ImageView) v.findViewById(R.id.frage_bild); frage = (TextView) v.findViewById(R.id.frage_frage); ueberschrift = (TextView) v.findViewById(R.id.frage_ueberschrift); auswahlA = (RadioButton) v.findViewById(R.id.frage_auswahl1); auswahlB = (RadioButton) v.findViewById(R.id.frage_auswahl2); auswahlC = (RadioButton) v.findViewById(R.id.frage_auswahl3); frageZusatz1 = (TextView) v.findViewById(R.id.frage_zusatz1); frageZusatz2 = (TextView) v.findViewById(R.id.frage_zusatz2); viewA = (View) v.findViewById(R.id.fake_view1); viewB = (View) v.findViewById(R.id.fake_view2); viewC = (View) v.findViewById(R.id.fake_view3); auswahlC.setEnabled(false); bild.setOnClickListener(this); auswahlA.setOnClickListener(this); auswahlB.setOnClickListener(this); auswahlC.setOnClickListener(this); auswahlA.setEnabled(false); auswahlB.setEnabled(false); bild.setClickable(false); if(WaldViewPager.getFrage(2)){ ZeigeFrage.unhide(2); } ueberschrift.setMovementMethod(LinkMovementMethod.getInstance()); frage.setMovementMethod(LinkMovementMethod.getInstance()); frageZusatz1.setMovementMethod(LinkMovementMethod.getInstance()); frageZusatz2.setMovementMethod(LinkMovementMethod.getInstance()); frageZusatz1.setText(ClickableText.addClickablePart(stringFrageZusatz1, WaldViewPager.getContext(), root), BufferType.SPANNABLE); frageZusatz2.setText(ClickableText.addClickablePart(stringFrageZusatz2, WaldViewPager.getContext(), root), BufferType.SPANNABLE); auswahlA.setText(stringAuswahlA); auswahlB.setText(stringAuswahlB); auswahlC.setText(stringAuswahlC); ueberschrift.setText(ClickableText.addClickablePart(stringUeberschrift, WaldViewPager.getContext(), root), BufferType.SPANNABLE); frage.setText(ClickableText.addClickablePart(stringFrage, WaldViewPager.getContext(), root), BufferType.SPANNABLE); if(WaldViewPager.getTextSize()!=0){ auswahlA.setTextSize(auswahlA.getTextSize()-WaldViewPager.getTextSize()); auswahlB.setTextSize(auswahlB.getTextSize()-WaldViewPager.getTextSize()); auswahlC.setTextSize(auswahlC.getTextSize()-WaldViewPager.getTextSize()); ueberschrift.setTextSize(ueberschrift.getTextSize()-WaldViewPager.getTextSize()); frage.setTextSize(frage.getTextSize()-WaldViewPager.getTextSize()); frageZusatz1.setTextSize(frageZusatz1.getTextSize()-WaldViewPager.getTextSize()); frageZusatz2.setTextSize(frageZusatz2.getTextSize()-WaldViewPager.getTextSize()); } return v; } @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isVisibleToUser) { if(WaldViewPager.getFrage(2)){ ZeigeFrage.unhide(2); } } } @Override public void onClick(View v) { if(v == bild){ Intent intent = new Intent(WaldViewPager.getContext(), ShowImage.class); WaldViewPager.bitmap = R.drawable.frage2; startActivity(intent); } if(v == auswahlA){ WaldViewPager.setAntwort(WaldViewPager.getPage(), 1); WaldViewPager.setPageVisible(3, true); WaldViewPager.setErgebnis(0); WaldViewPager.setPage(3); } if(v == auswahlB){ //coptoformica WaldViewPager.setAntwort(WaldViewPager.getPage(), 2); WaldViewPager.setErgebnis(2); Intent intent = new Intent(WaldViewPager.getContext(), ErgebnisB.class); startActivity(intent); } if(v == auswahlC){ } } } ``` My decodeImage ``` public class DecodeImage { public static Bitmap decode(Resources res, int resId){ BitmapFactory.Options bfOptions=new BitmapFactory.Options(); bfOptions.inDither = false; bfOptions.inPurgeable = true; bfOptions.inInputShareable = true; bfOptions.inTempStorage = new byte[32 * 1024]; return BitmapFactory.decodeResource(res, resId, bfOptions); } } ``` I would appreciate any help. feel free to ask for over peaces of code. this app works fine on some devices but on other not. has to be something with heap size change i guess. EDIT: found the solution. the answer with the `bitmap.recycle()` works but due to my art of code i was lazy to change a lot and i used something else. as for `ViewPager` android provides you with ``` @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); } ``` i upgraded the line ``` @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isVisibleToUser) { //if you can see the fragment }else{ //if you dont } } ``` to ``` @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isVisibleToUser) { //if you can see the fragment }else{ //if you dont imageViewToDelete.setImageDrawable(null); //this is ImageView from Fragment } } ``` REMEMBER: `setUserVisibleHint()` is set earlier than the `onCreateView()` good luck

Original source

Related problems