Start Before You Finish

Let’s take “a trip down Memory Lane” and talk a bit about API design, using as an example a common thing in Android: starting and finishing activities.

The Scenario

Particularly in activity-centric UI architectures, there may be cases where we want to show an activity, then switch to a different activity, where the first activity is no longer needed in the back stack. A common example of this is the splash screen:

graph LR Launcher --> Splash Splash --> Main Main -->|BACK pressed| Launcher

If the user is in Main and presses BACK, we do not want the user to wind up in Splash — instead, they should exit the app and return to the launcher (or wherever they started from).

So, in Splash, we could call startActivity() to start Main, plus call finish() to remove Splash from the task.

However, do we:

  • Call startActivity(), then finish()?
  • Call finish(), then startActivity()?
  • Do either of those, as the order of calls does not matter?

The Answer

Vitaliy Khudenko decided to research this topic, and he concluded that the right answer is to call startActivity(), then finish().

In the scenario that I just described, where Splash is the only one in the task, if we call finish() before startActivity(), Android will add FLAG_ACTIVITY_NEW_TASK automatically to the Intent used in the startActivity() call. If we call startActivity() first, Android does not add this flag. And, it is possible that this flag may have an impact on the behavior of the activity being started.

The Knowledge Gap

This behavior is undocumented, as far as Vitaliy and I can tell. Vitaliy filed an issue to try to get this covered.

From an API design standpoint, though, could we do better?

Clearly, we need to be able to call startActivity() without always finishing. Similarly, we will have cases where we need to call finish() without starting another activity. As a result, we need the two existing primitive methods.

However, in cases where you have a pair of simple calls, where there is a preferred way for them to be used in combination, consider adding something to the API that helps developers “do the right thing”. In this case, that could be:

  • A flag on startActivity() to indicate if the current activity should then finish

  • A startActivityAndFinish() method that does both actions in the typical order

  • Have startActivity() return an ActivityStartContinuation, on which there is a thenFinish() function, so we can write startActivity(...).thenFinish()

  • And so on

Now, the Android SDK is vast, and adding these sorts of things makes it even more vast (vaster?). In that case, going the documentation route may be preferable. And of course there is nothing stopping you from adding convenience methods and documenting the reason for them.

But, ideally, your SDK calls out scenarios like this and helps developers easily do what most developers would want, with the flexibility of supporting other, less-common options.

Many thanks to Vitaliy for pointing out the problem!

Find out about new posts on the CommonsBlog via the Atom feed, or follow @CommonsWare on Twitter!