Android 我的应用程序使用了大量Ram,并意外关闭
现在我几乎完成了我的应用程序。说实话,我对应用程序的设计很满意。我正在拍摄照片,让它看起来更漂亮。 我遇到了一个问题。 首先,我想解释是什么让这个应用程序,这样他们就能更好地理解这个问题 该应用程序是一个问题游戏,答案是真是假。每个问题都有一个图像。 每个问题都是一个片段,将随fragmentManager而改变 没有图像的应用程序问题可以完美地工作。但添加图像后,应用程序在到达最后一个问题时会自动停止并关闭 1-使用带有Android 2.1的虚拟机,应用程序不会停止,但如果速度变慢。 2-使用带有安卓4.4.4应用程序的移动xperia Z2到达问题编号10停止并关闭 我认为问题在于管理内存位图 但是如何实现管理内存位图来清理图像使用的内存 第一组问题的主要代码是:Android 我的应用程序使用了大量Ram,并意外关闭,android,android-fragments,memory-leaks,bitmap,android-memory,Android,Android Fragments,Memory Leaks,Bitmap,Android Memory,现在我几乎完成了我的应用程序。说实话,我对应用程序的设计很满意。我正在拍摄照片,让它看起来更漂亮。 我遇到了一个问题。 首先,我想解释是什么让这个应用程序,这样他们就能更好地理解这个问题 该应用程序是一个问题游戏,答案是真是假。每个问题都有一个图像。 每个问题都是一个片段,将随fragmentManager而改变 没有图像的应用程序问题可以完美地工作。但添加图像后,应用程序在到达最后一个问题时会自动停止并关闭 1-使用带有Android 2.1的虚拟机,应用程序不会停止,但如果速度变慢。 2-使
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个片段,这些片段中都有一个大位图
android.support.v4.app.FragmentManager managerAsk = getActivity().getSupportFragmentManager();
managerAsk.beginTransaction()
.hide(toHide1)
.hide(toHide2)
...
.show(toShow)
.commit();
考虑到您只需要显示一个片段,程序的结构应确保始终只创建一个片段。事实上,我甚至不确定是否应该有两个以上的片段grpE和grpP,这取决于它们是否真的改变了布局,还是仅仅改变了内容
如果不能做到这一点,至少使用FragmentStatePagerAdapter这样的机制,这样就不会实际创建您不需要的片段,从而占用内存。您的问题是,实际上内存中始终有所有20个片段,而这些片段中都有一个大位图
android.support.v4.app.FragmentManager managerAsk = getActivity().getSupportFragmentManager();
managerAsk.beginTransaction()
.hide(toHide1)
.hide(toHide2)
...
.show(toShow)
.commit();
考虑到您只需要显示一个片段,程序的结构应确保始终只创建一个片段。事实上,我甚至不确定是否应该有两个以上的片段grpE和grpP,这取决于它们是否真的改变了布局,还是仅仅改变了内容
如果无法做到这一点,至少使用类似FragmentStatePagerAdapter的机制,这样就不会实际创建您不需要的片段,从而占用内存。您使用了许多片段,每个片段都具有ImageView布局 你的方法似乎是: 每一个问题都是新的片段,都有新的布局。你在展示 当问题显示时,显示该片段 为什么你的方法没有优化 在问题集中添加新问题时,您将添加多少次新片段。您当前的方法是静态的,您需要为新问题手动添加片段和布局 当碎片进入应用程序时,Android DVM可以节省更多堆大小。您正在初始化应用程序中的许多片段。这使用的堆大小比需要的大得多,大约199MB 以上各点的解决方案: 最好使用较少的片段和相应的布局。当您需要显示下一个问题时,只需将当前布局文本字段和图像字段替换为下一个问题信息即可。这样,当您想要显示新问题时,就不需要手动添加片段 取消所有未使用的ImageView。这样你就可以防止内存泄漏,还有更多防止内存泄漏的方法:谷歌工程师提供的优秀视频肯定会对你有所帮助
您使用了许多片段,每个片段都有带有ImageView的布局 你的方法似乎是: 每一个问题都是新的片段,都有新的布局。你在展示 当问题显示时,显示该片段 为什么你的方法没有优化 在问题集中添加新问题时,您将添加多少次新片段。您当前的方法是静态的,您需要为新问题手动添加片段和布局 当碎片进入应用程序时,Android DVM可以节省更多堆大小。您正在初始化应用程序中的许多片段。这使用的堆大小比需要的大得多,大约199MB 以上各点的解决方案: 最好使用较少的片段和相应的布局。当您需要显示下一个问题时,只需将当前布局文本字段和图像字段替换为下一个问题信息即可。这样,当您想要显示新问题时,就不需要手动添加片段 取消所有未使用的ImageView。这样你就可以防止内存泄漏,还有更多防止内存泄漏的方法:谷歌工程师提供的优秀视频肯定会对你有所帮助
堆栈跟踪显示了什么?它是否显示内存不足?在哪里加载图像?我看不到密码
这里是关于实际图像的显示方式,除非这里刚刚指定android:src=@mipmap/img1,它在不需要它们时不会缓存它们。我猜,无论如何:-无论哪种方式,在显示它们之前,你都应该调整位图的大小,我建议使用毕加索库加载图像。这是由于ImageView。每个片段都使用一个大小为200x200dp的大ImageView,每个这样的ImageView在mdpi屏幕上需要大约300kb的RAM。我建议您不要在开始时创建所有片段,而是逐个切换它们,以便一次只创建1个片段。堆栈跟踪说明了什么?它是否显示内存不足?在哪里加载图像?我在这里看不到关于实际图像显示方式的代码,除非这里只是指定了android:src=@mipmap/img1,它在不需要它们时不会缓存它们。我猜,无论如何:-无论哪种方式,在显示它们之前,你都应该调整位图的大小,我建议使用毕加索库加载图像。这是由于ImageView。每个片段都使用一个大小为200x200dp的大ImageView,每个这样的ImageView在mdpi屏幕上需要大约300kb的RAM。我建议您不要在开始时创建所有片段,而是逐个切换它们,以便一次只创建1个片段。非常感谢Kushal,我通过TextView更改了片段,这将随setText更改。我还放置了将随setImageResource更改的Imagevew。该应用程序显著减少了内存使用。现在几乎没有什么记忆了。我非常感激。在这个网站上我学到了很多。还要感谢:EpicPandaForce,Stan,InMystry.谢谢。。我很高兴你的问题解决了。。喜欢学习非常感谢Kushal,我通过TextView更改了片段,这些片段将随setText更改。我还放置了将随setImageResource更改的Imagevew。该应用程序显著减少了内存使用。现在几乎没有什么记忆了。我非常感激。在这个网站上我学到了很多。还要感谢:EpicPandaForce,Stan,InMystry.谢谢。。我很高兴你的问题解决了。。享受学习