Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: OutOfMemory error and the backstack

the following sheet represents the working flow in the application this question is about.

workflow

I ran into problems with OutOfMemory Errors, mostly because users were able to switch from activity B to activity D multiple times (They are showing different content for every attempt), without the previous activity being destroyed. This led into a very large backstack resulting in an OutOfMemory error.

To avoid this, I followed the recommendation to add parent activites to the manifest and create new backstacks with the TaskStackBuilder class:

void openDFromB()
{
    Intent i = new Intent(this, ActivityD.class);
    TaskStackBuilder.create(this)
        .addParentStack(ActivityD.class)
        .addNextIntent(i)
        .startActivities();
}

If a user now switches from activity B to D, MainMenu, A and B are destroyed and a new Backstack (MainMenu, C, D) is created. This solves my memory problems for api level greater 10, but unfortunately the TaskStackBuilder does not create backstacks for devices pre api 11.

Any idea what to do in order to avoid users stacking infinite amounts of activities prior api 11? Is this even possible or should I try to free as many resources as possible in onPause to gain a maximum amount of stacked activities before OoM?

thanks in advance!

like image 513
danijoo Avatar asked Dec 09 '13 11:12

danijoo


2 Answers

Try this-

Intent intent = new Intent(getApplicationContext(),yourActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

Another solution is-

Setting android:noHistory="true" on the activity in your manifest file will remove an activity from the stack whenever it is navigated away from.

But the most appropriate way is to call finish() method whenever you start new activity like in the following sample code-

Intent intent = new Intent(this, yourActivity.class);
startActivity(intent);
finish();

You can also create custom Broadcast receiver and register it in every activity which can be fired on event of your choice. For more help you can check this link.

like image 62
Kanwaljit Singh Avatar answered Sep 21 '22 09:09

Kanwaljit Singh


Zabri answer is good, but i would propose another probably is better: You dont close every activity, but when you are opening a new activity that has been open before, you tell the system that it can clear the way back and reopen that one, of course with a new intent and all the new data that you need.

So, if you do A - B - D - B - D - B, instead of having that big stack,you will have

  1. A - B
  2. A - B - D
  3. A - B
  4. A - B - D
  5. A - B

So, if you do C - D - B - D - B - D, your stack will be

  1. C - D
  2. C - D - B
  3. C - D
  4. C - D - B
  5. C - D

and so on. In this way, i think the stack actually reflects what the user can have in mind, and also navigation is very logic, you don't even need to captre back button to have the navigation making sense, (of course you can do it if you want a more specific user experience)

The code to achieve this, is: create a function that receives a class (something like ActivityD.class), there you create an intent, with the flags Intent.FLAG_ACTIVITY_CLEAR_TOP and Intent.FLAG_ACTIVITY_NEW_TASK and then when you need to open an activity, just call this function. You dont care about if the activity is in the stack or not. If it isnt,it is created normally.

 protected void startActivity(Class<?> clase) {
    final Intent i = new Intent(this, clase);
    int flags = Intent.FLAG_ACTIVITY_CLEAR_TOP;
    flags |= Intent.FLAG_ACTIVITY_NEW_TASK;
    i.setFlags(flags);
    startActivity(i);
}


startActivity(ActivityD.class);
like image 35
Carlos Robles Avatar answered Sep 24 '22 09:09

Carlos Robles