android viewpager内存不足

时间:2013-08-09 09:58:19

标签: android android-viewpager out-of-memory

首先,我想说英语不是我的母语。所以请原谅我的错误。

我的问题:我有一个ViewPager,有10页和标签。第一个窗口用于设置,其他窗口用于设置。

您从第一个问题开始,我会显示一个图像,如果您点击“是”“否”,那么您将转到下一页,其中第二张图片会显示另一个问题。

我每次都得到oom错误(因为我到了7页)。我读了一些关于它的tipps我现在每次使用位图解码器将图像绑定到我的ImageView。但这并没有多大帮助。我还有同样的问题。我的解码器有*.inPurgeable = true;

我知道有一个选项可以更改您的manifest.xml以允许更多的堆大小,但我认为这只会延迟错误。有人可以查看我的代码并告诉我一些我做错了。因为在我看来这很好,但因为我是编程的新手,我本可以犯一些重大错误:)

我带有适配器的viewpager:

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);
    }
}

我的一个问题:

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){

        }
    }
}

我的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);
    }
}

我将不胜感激任何帮助。随意请求代码的和平。 这个应用程序在某些设备上运行正常,但在其他设必须是堆大小改变的东西我猜。

编辑:找到了解决方案。 bitmap.recycle()的答案有效,但由于我的代码艺术,我懒得改变很多,而且还用了别的东西。

至于ViewPager android为你提供了

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
}

我升级了行

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) { 
        //if you can see the fragment
    }else{
        //if you dont
    }
}

@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
    }
}

记住: setUserVisibleHint()的设置早于onCreateView()

祝你好运

4 个答案:

答案 0 :(得分:5)

对于每个imageView,您必须调用recycle()方法。所以,在行之前:

  

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

你必须把这行:

  

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

如果问题仍然存在,那是因为图像太大而你必须压缩它

答案 1 :(得分:1)

我面临同样的问题并解决了它,如下

最好的例子在android开发者指南中给出,按照本指南一步一步。

1.Iustment inJustDecodeBounds http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

2.按照以下异步和缓存指南,您也可以从同一链接下载示例。 http://developer.android.com/training/displaying-bitmaps/display-bitmap.html

答案 2 :(得分:1)

OutOfMemory图片(720 * 1200)出现ViewPager错误。结合建议我找到了适合我的解决方案:

  
      
  • 将图片放入drawable-nodpi类别(从所有其他可绘制类别中移除)

  •   
  • 使用选项将drawable解码为位图(inSampleSize = 1,ARGB_8888)

  •   

答案 3 :(得分:1)

我正在使用 Picasso 并且也遇到了这个问题...... 只需删除放入ImageView的虚拟内容即可。删除src标签,因为Picasso不需要它。

<ImageView
        android:id="@+id/img"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:scaleType="centerCrop"
        **android:src="@drawable/myDrawable"**/>

发生这种情况是因为必须加载drawables,即使之后用Picasso替换它们,并且在将许多图像加载到ViewPager之后,它会导致OutOfMemory。