草庐IT

android viewpager 内存不足

coder 2023-12-01 原文

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

对于我的问题:我有一个包含 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 viewpager 内存不足的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby-on-rails - Ruby 中的内存模型 - 2

    ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序

  3. 键删除后 ruby​​ 哈希内存泄漏 - 2

    你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p

  4. ruby-on-rails - HTTParty 的内存问题和下载大文件 - 2

    这会导致Ruby出现内存问题吗?我知道如果大小超过10KB,Open-URI会写入TempFile。但是HTTParty会在写入TempFile之前尝试将整个PDF保存到内存吗?src=Tempfile.new("file.pdf")src.binmodesrc.writeHTTParty.get("large_file.pdf").parsed_response 最佳答案 您可以使用Net::HTTP。参见thedocumentation(特别是标题为“流媒体响应机构”的部分)。这是文档中的示例:uri=URI('http://e

  5. ruby - 现代计算机的功能是否不足以处理字符串而无需使用符号(在 Ruby 中) - 2

    我读过的关于Ruby符号的每一篇文章都在谈论符号相对于字符串的效率。但是,这不是1970年代。我的电脑可以处理一些额外的垃圾收集。我错了吗?我拥有最新最好的奔腾双核处理器和4GBRAM。我认为这应该足以处理一些字符串。 最佳答案 您的计算机可能能够处理“一点点额外的垃圾收集”,但是当“一点点”发生在运行数百万次的内部循环中时呢?如果它在内存有限的嵌入式系统上运行呢?有很多地方你可以随意使用字符串,但在某些地方你不能。这完全取决于上下文。 关于ruby-现代计算机的功能是否不足以处理字符串

  6. ruby-on-rails - 内存中具有相同 ID 的更多对象? - 2

    在部署在heroku上的Rails应用程序(v:3.1)中,我在内存中获得了更多具有相同ID的对象。我的heroku控制台日志:>>Project.find_all_by_id(92).size=>2>>ActiveRecord::Base.connection.execute('select*fromprojectswhereid=92').to_a.size=>1这怎么可能?可能是什么问题? 最佳答案 解决方案根据您的SQL查询,您的数据库中显然没有重复条目。也许您的类项目中的size或length方法已被覆盖。我试过find_

  7. ruby - rails 3.0.7 内存泄漏 - 2

    我的两个不同的Rails应用程序的内存有一些奇怪的问题。这两个应用程序都使用rails3.0.7。每个Controller请求分配20-30-50MB的内存。在生产模式下,这个数量减少到5-10。但这是同样的事情。这是两个应用程序使用的gem列表:gem'pg'gem'haml'gem'sass'gem'devise'gem'simple_form'gem'state_machine'gem"globalize3","0.1.0.beta"gem"easy_globalize3_accessors"gem'paperclip'gem'andand'关闭所有这些gem不会给我任何结果。我

  8. ruby - 如何强制 Ruby 释放内存给操作系统 - 2

    正如标题,我有一个处理大量数据的ruby​​程序。该程序占用了所有内存,其中调用了系统命令hostname,并且发生错误无法分配内存-主机名我试过GC.start但它不起作用。那么如何强制ruby释放未使用的内存呢?OK,这是别人的测试代码,最后报错是big_var被回收了。但是内存仍然没有释放。require"weakref"defreportputs"#{param}:\t\tMemory"+`psax-opid,rss|grep-E"^[[:space:]]*#{$$}"`.strip.split.map(&:to_i)[1].to_s+'KB'endbig_var=""#big

  9. ruby - 如何在 Ruby 中从内存中 HTTP 发布流数据? - 2

    我想上传我在运行时用Ruby生成的数据,就像从block中提供上传数据一样。我找到的所有示例仅展示了如何流式传输必须在请求之前位于磁盘上的文件,但我不想缓冲该文件。除了滚动我自己的套接字连接之外,最好的解决方案是什么?这是一个伪代码示例:post_stream('127.0.0.1','/stream/')do|body|generate_xmldo|segment|body 最佳答案 有效的代码。require'thread'require'net/http'require'base64'require'openssl'class

  10. ruby-on-rails - 如何仅修改内存中的 zip 文件? - 2

    我有一个Ruby应用程序,我需要修改现有的zip文件。我想在内存中构建zip文件并流回字节,而无需将文件写入文件系统。如果我最终在Heroku上托管它,我认为我无法写入文件系统。有谁知道这样做的方法吗?我看了Zip::ZipFile但看起来它总是想写入文件系统。我想“基于java实现”我将能够只获取压缩文件的字节,这可以在java中完成,但我看不到这样做的方法。编辑:我要问的与此基本相同,但针对Ruby而不是Python:Functiontocreatein-memoryzipfileandreturnashttpresponse 最佳答案

随机推荐