我的应用程序使用了大量的Ram并意外关闭

时间:2015-04-22 11:33:28

标签: android android-fragments memory-leaks bitmap android-memory

现在我差不多完成了我的应用。说实话,我与应用程序的设计。我得到的图像让它看起来更漂亮。 而且我遇到了一个问题。 首先,我想解释一下制作应用程序的原因,以便他们更好地理解这个问题。

该应用程序是一个问题游戏,答案是真是假。每个问题都有一个图像。 每个问题都是一个片段,它将随fragmentManager一起发生变化。

没有图像的应用程序问题完美无缺。但是添加图像时,应用程序在到达最后一个问题时会自动停止和关闭。

1-使用安装了Android 2.1的虚拟机,应用程序不会停止,但如果速度变慢。 2-使用带有Android 4.4.4应用程序的移动xperia Z2进入问题编号10停止和关闭。

我认为问题是管理内存位图。

但是如何实现Managing Memory Bitmap来清理图像使用的内存。

第一组问题的主要代码是:

public class Grp1Fragment extends Fragment {

    private int ContArrayAsk = 0;
    private int ContRight = 0;
    private int ContFailed= 0;
    private int ContArrayResults =0;
    private String msg = "";

    private Button buttonTrue;
    private Button buttonFalse;
    private Button buttonNextAsk;
    private Button buttonShareScore;

    private View view;



    String[] arrayFragmentAResultsGrp1 = new String[]{"false","false","false","true","false","true","true","true","false","true",};

    private Fragment[] fragmentsChangeAsk = new Fragment[]{
                                                    new Grp1FragmentP1(),
                                                    new Grp1FragmentE1(),
                                                    new Grp1FragmentP2(),
                                                    new Grp1FragmentE2(),
                                                    new Grp1FragmentP3(),
                                                    new Grp1FragmentE3(),
                                                    new Grp1FragmentP4(),
                                                    new Grp1FragmentE4(),
                                                    new Grp1FragmentP5(),
                                                    new Grp1FragmentE5(),
                                                    ...

                                };

    public Grp1Fragment() {
        // Required empty public constructor


    }


    @Override
    public void onActivityCreated(Bundle savedInstanceState){
        super.onActivityCreated(savedInstanceState);

        android.support.v4.app.FragmentManager managerAsk = getActivity().getSupportFragmentManager();
        managerAsk.beginTransaction()
                .add(R.id.fragmentaskGRP1, fragmentsChangeAsk[0])
                .add(R.id.fragmentaskGRP1, fragmentsChangeAsk[1])
                ...
                .hide(fragmentsChangeAsk[1])
                .hide(fragmentsChangeAsk[2])
        ...
                .commit();
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.fragment_grp1, container, false);
        return view;
    }


    @Override
    public void onViewCreated(View view, Bundle savedInstanceState){
        super.onViewCreated(view, savedInstanceState);


        buttonTrue = (Button) view.findViewById(R.id.buttontruegpr1);
        if(buttonTrue != null){
            buttonTrue.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    if (arrayFragmentAResultsGrp1[ContArrayResults].equals("true")) {
                        Toast.makeText(getActivity(), "Respuesta correcta", Toast.LENGTH_SHORT).show();
                        ContRight++;
                        ContArrayAsk++;
                        ContArrayAsk++;
                        ContArrayResults++;
                        setContent(ContArrayAsk);
                        validarpantallafinal();
                    }else{
                        Toast.makeText(getActivity(), "Respuesta incorrecta", Toast.LENGTH_SHORT).show();
                        ContFailed++;
                        ContArrayAsk++;
                        ContArrayResults++;
                        setContent(ContArrayAsk);
                        buttontrueorfalsedisabled();
                        validarpantallafinal();
                    }
                }
            });
        }


        buttonFalse = (Button) view.findViewById(R.id.buttonfalsegpr1);
        if(buttonFalse != null) {
            buttonFalse.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    if (arrayFragmentAResultsGrp1[ContArrayResults].equals("false")) {
                        Toast.makeText(getActivity(), "Respuesta correcta", Toast.LENGTH_SHORT).show();
                        ContRight++;
                        ContArrayAsk++;
                        ContArrayAsk++;
                        ContArrayResults++;
                        setContent(ContArrayAsk);
                        validarpantallafinal();
                    } else {
                        Toast.makeText(getActivity(), "Respuesta incorrecta", Toast.LENGTH_SHORT).show();
                        ContFailed++;
                        ContArrayAsk++;
                        ContArrayResults++;
                        setContent(ContArrayAsk);
                        buttontrueorfalsedisabled();
                        validarpantallafinal();
                    }
                }
            });
        }


        buttonNextAsk = (Button) view.findViewById(R.id.buttonnextaskgrp1);
        buttonNextAsk.setEnabled(false);
        buttonNextAsk.setVisibility(View.INVISIBLE);
        if(buttonFalse != null) {
            buttonNextAsk.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    //Toast.makeText(getActivity(), "Ha pulsado el botón siguiente pregunta", Toast.LENGTH_LONG).show();
                    buttontrueorfalseenabled();
                    ContArrayAsk++;
                    setContent(ContArrayAsk);
                    validarpantallafinal();
                }
            });
        }


        buttonShareScore = (Button) view.findViewById(R.id.buttonsharescoregrp1);
        buttonShareScore.setEnabled(false);
        buttonShareScore.setVisibility(View.INVISIBLE);
        if(buttonShareScore != null) {
            buttonShareScore.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    msg = msg.concat(getString(R.string.message_share_score_grp1) +
                                                "\nPreguntas acertadas: "+ Integer.toString(ContRight) +
                                                "\nPreguntas falladas: " + Integer.toString(ContFailed) +
                                                "\n" + getString(R.string.message_share));
                    Intent intent = new Intent();
                    intent.setAction(Intent.ACTION_SEND);
                    intent.putExtra(Intent.EXTRA_TEXT, msg);
                    intent.setType("text/plain");
                    startActivity(Intent.createChooser(intent,
                            getString(R.string.action_share)));
                    //Toast.makeText(getActivity(), "Ha pulsado el botón compartir resultados\nAciertos:" + Integer.toString(ContRight) + "\nFallos:" + Integer.toString(ContFailed), Toast.LENGTH_LONG).show();
                }
            });
        }

    }

    public void buttontrueorfalseenabled(){
        buttonTrue.setEnabled(true);
        buttonTrue.setVisibility(View.VISIBLE);
        buttonFalse.setEnabled(true);
        buttonFalse.setVisibility(View.VISIBLE);
        buttonNextAsk.setEnabled(false);
        buttonNextAsk.setVisibility(View.INVISIBLE);
    }

    public void buttontrueorfalsedisabled(){
        buttonTrue.setEnabled(false);
        buttonTrue.setVisibility(View.INVISIBLE);
        buttonFalse.setEnabled(false);
        buttonFalse.setVisibility(View.INVISIBLE);
        buttonNextAsk.setEnabled(true);
        buttonNextAsk.setVisibility(View.VISIBLE);
    }

    public void validarpantallafinal(){
        if (ContArrayAsk == fragmentsChangeAsk.length-1){
            buttonTrue.setEnabled(false);
            buttonTrue.setVisibility(View.INVISIBLE);
            buttonFalse.setEnabled(false);
            buttonFalse.setVisibility(View.INVISIBLE);
            buttonNextAsk.setEnabled(false);
            buttonNextAsk.setVisibility(View.INVISIBLE);
            buttonShareScore.setEnabled(true);
            buttonShareScore.setVisibility(View.VISIBLE);
            TextView score = (TextView) view.findViewById(R.id.textScoregrp1);
            score.setText("Felicidades, ha terminado las preguntas del apartado de Historia.\n"+
                           "Las preguntas acertadas son: " + Integer.toString(ContRight) +
                           "\nLas preguntas falladas son: " + Integer.toString(ContFailed));

        }
    }

    public void setContent(int index){

        Fragment toHide1 = null;
        Fragment toHide2 = null;
        Fragment toHide3 = null;
        Fragment toHide4 = null;
        Fragment toHide5 = null;
        Fragment toHide6 = null;
        Fragment toHide7 = null;
        Fragment toHide8 = null;
        Fragment toHide9 = null;
        Fragment toHide10 = null;
        Fragment toHide11 = null;
        Fragment toHide12 = null;
        Fragment toHide13 = null;
        Fragment toHide14 = null;
        Fragment toHide15 = null;
        Fragment toHide16 = null;
        Fragment toHide17 = null;
        Fragment toHide18 = null;
        Fragment toHide19 = null;
        Fragment toHide20 = null;
        Fragment toShow = null;

        switch (index){
            case 0:
                toHide1 = fragmentsChangeAsk[1];
                toHide2 = fragmentsChangeAsk[2];
                toHide3 = fragmentsChangeAsk[3];
                toHide4 = fragmentsChangeAsk[4];
                toHide5 = fragmentsChangeAsk[5];
                toHide6 = fragmentsChangeAsk[6];
                toHide7 = fragmentsChangeAsk[7];
                toHide8 = fragmentsChangeAsk[8];
                toHide9 = fragmentsChangeAsk[9];
                toHide10 = fragmentsChangeAsk[10];
                toHide11 = fragmentsChangeAsk[11];
                toHide12 = fragmentsChangeAsk[12];
                toHide13 = fragmentsChangeAsk[13];
                toHide14 = fragmentsChangeAsk[14];
                toHide15 = fragmentsChangeAsk[15];
                toHide16 = fragmentsChangeAsk[16];
                toHide17 = fragmentsChangeAsk[17];
                toHide18 = fragmentsChangeAsk[18];
                toHide19 = fragmentsChangeAsk[19];
                toHide20 = fragmentsChangeAsk[20];
                toShow = fragmentsChangeAsk[0];
                break;
            case 1:
                toHide1 = fragmentsChangeAsk[0];
                toHide2 = fragmentsChangeAsk[2];
                ...
        case 20:
        ...
        }
        android.support.v4.app.FragmentManager managerAsk = getActivity().getSupportFragmentManager();
        managerAsk.beginTransaction()
                .hide(toHide1)
                .hide(toHide2)
                ...
                .show(toShow)
                .commit();

    }


}

如何用图像显示问题的示例:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent"
    android:id="@+id/fragment_grp1_e1">


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/GRP1error1"
        android:id="@+id/textViewGrp1e1"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        style="@style/textAsk"/>

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:contentDescription="@string/impask"
        android:src="@mipmap/img1"
        android:layout_below="@+id/textViewGrp1e1"
        android:layout_centerHorizontal="true" />

</RelativeLayout>

在Android Studio中,您可以看到已用内存。当我运行应用程序时,它使用188Mb。当应用程序使用很快达到190MB。

我们使用的图像重量不超过300kb。 并且已安装的应用程序的重量为6Mb。

非常感谢您的帮助

2 个答案:

答案 0 :(得分:3)

你的问题是你实际上总是在内存中所有20个片段,它们都有一个大的位图。

    android.support.v4.app.FragmentManager managerAsk = getActivity().getSupportFragmentManager();
    managerAsk.beginTransaction()
            .hide(toHide1)
            .hide(toHide2)
            ...
            .show(toShow)
            .commit();

程序的结构应使得始终只创建一个片段,考虑到您只需要显示的一个片段。事实上,我甚至不确定应该是否超过两个片段(grpE和grpP),这取决于它们是真正改变布局,还是只改变内容。

如果无法做到这一点,至少要使用像FragmentStatePagerAdapter这样的机制,以便实际上不会创建你不需要的片段,占用内存。

答案 1 :(得分:2)

您正在使用许多片段,每个片段都有ImageView布局。

您的方法似乎是:

  

每个问题都是新的片段并且有新的布局。你正在展示   问题显示时片段化。

为什么你的approch没有优化?

  • 问题集中添加新问题时,您会在多长时间内添加新的片段。您当前的方法是静态,您需要为新问题添加手动片段和布局
  • 当片段进入应用程序时,Android DVM不再使用更多的堆大小。您正在应用程序中初始化许多片段。这使用的堆大小远远超过必要(大约199MB)

解决上述问题:

  • 更好地使用更少片段和相应的布局。当您需要显示下一个问题时,只需replace当前布局文本字段和带有下一个问题信息的图像字段。这样,当您想要显示新问题时,您不需要手动添加片段
  • Nullify任何未使用的ImageView。通过这种方式可以防止内存泄漏有关防止内存泄漏的更多方法:来自Google工程师Google IO Memory optimization的精彩视频肯定会帮助您