android viewpager 内存不足

标签 android android-viewpager out-of-memory

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

对于我的问题:我有一个包含 10 个页面和选项卡的 ViewPager。第一个窗口用于设置,其他窗口为问题。

你从第一个问题开始,我显示一张图片,如果你点击"is"“否”,那么你会转到下一页,第二张图片显示另一个问题。

我每次都会遇到 oom 错误(当我到达第 7 页时)。我阅读了一些关于它的技巧,现在我每次将图像绑定(bind)到我的 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){

        }
    }
}

我的解码图像

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

祝你好运

最佳答案

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

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

你必须把线:

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

如果问题依然存在,那是因为图片太大了,需要压缩一下

关于android viewpager 内存不足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18144132/

相关文章:

android-layout - CoordinatorLayout不适用于ViewPager中Fragment中的NestedScrollView

android - FloatingActionButton 在 ViewPager 中不可见

android - 如何使用 viewpager 从选项卡布局中的 recyclerview 重新加载 fragment ?

java - 在Windows中使用Eclipse增加Java堆大小

android - 执行任务时 React Native 构建失败 > 路径不是可读目录

Android Studio 覆盖率报告未在带注释的方法上运行

android - 具有不同重力和高度的单个 TextView 中的两种不同样式

JavaScript棋盘游戏: looking for optimization

Java 字符串内存泄漏 II

java - 如何知道特定功能的内存使用情况?