Now I have almost finished my app. To tell the truth and I am with the design of the app. I'm getting images to make it look prettier. And I've run into a problem. First I want to explain what makes the app, so they can better understand the problem.
The app is a game of questions, the answers are true or false. Each question has an image. Each question is a fragment that will change with fragmentManager.
The application questions without images works perfectly. But adding images, the application when it reaches the last question stops and closes automatically.
1- Using a virtual machine with Android 2.1, the application does not stop, but if you are getting slower. 2- Using a mobile xperia Z2 with Android 4.4.4 application to get to the question number 10 stops and closes.
I think the problem is the Managing Memory Bitmap.
But how to implement the Managing Memory Bitmap to clean the memory used by the images.
The main code of the first group of questions is:
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();
}
}
Example of how to show the question with the image:
<?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>
In Android Studio you can see the used memory. When I run the app it uses 188Mb. When the app is used soon reaches 190MB.
The images we use weigh no more than 300kb. And the weight of the installed app is 6Mb.
Thank you very much for your help
You are using Many Fragments and each have layout with ImageView.
Your approach seems like :
Every question is new Fragment and has new layout. You are showing that Fragment when question displays.
Why your approch is not optimized ?
Solution to above points :
replace
current layout textfield and imagefield with next question information. This way you do not require to add fragments manually when you want to display new questionNullify
any ImageViews which are not in use. This way you will prevent memory leaks For more way to prevent memory leak : an excellent video from Google Engineers Google IO Memory optimization will definitely help you