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

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

现在我几乎完成了我的应用程序。说实话,我对应用程序的设计很满意。我正在获取图像以使其看起来更漂亮。 我遇到了一个问题。 首先,我想解释是什么造就了这个应用,这样他们就能更好地理解这个问题。

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

没有图像的应用问题完美运行。但添加图片时,应用程序会在遇到最后一个问题时停止并自动关闭。

1- 使用带有 Android 2.1 的虚拟机,应用程序不会停止,但如果您变慢了。 2- 使用装有 Android 4.4.4 应用程序的移动 xperia Z2 来解决问题编号 10 停止并关闭。

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

但是如何实现管理内存位图来清理图像使用的内存。

第一组题的主要代码是:

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。

非常感谢您的帮助

最佳答案

您的问题是您实际上内存中始终有所有 20 个 fragment ,其中都有一个大位图。

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

考虑到您只需要显示的一个 fragment ,程序的结构应该始终只创建一个 fragment 。事实上,我什至不确定是否应该有两个以上的 fragment (grpE 和 grpP),这取决于它们是否真的改变了布局,或者只是改变了内容。

如果那做不到,至少使用像FragmentStatePagerAdapter这样的机制,这样你不需要的 fragment 不会被实际创建,占用内存。

关于android - 我的应用程序使用大量 Ram 并意外关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29796249/

相关文章:

javascript - AJAX 应用程序和事件监听器的 JS 内存泄漏?

android - Android 中的矢量动态调整大小

android - Appium ERROR 转储失败,因为无法加载 Assets : Invalid file Support

android - fragment 必须是公共(public)静态类才能从实例状态正确地重新创建?

android - 从包中检索传递的参数时,为什么 Android Studio 会发出警告并建议使用 requireArguments() 而不是参数!!?

c++ - 查找数组之间的内存泄漏

java - Android Activity 问题 startActivity (我只想显示)

android - Robolectric 为具有换行内容高度的 View 返回 0 高度

android-fragments - 带有 SearchView 临时过滤 RecyclerView 的工具栏

c++ - 内核资源泄漏 BIO_do_connect