Android 14: cross-activity predictive back animation and lifecycle

Explore the impact of Android 14’s cross-activity predictive back animation on activity’s lifecycle

Vairavan Srinivasan
3 min readOct 13, 2023

Android 14 adds on to Android 13’s predictive back navigation by supporting animation across activities and tasks. However, the docs doesn’t call out its impact on activity lifecycle.

Here is an app with two activities, one starting the other upon FAB click with predictive back animations enabled in developer options. First activity has logs in appropriate lifecycle callbacks

class MainActivity : AppCompatActivity() {

private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
...

binding.fab.setOnClickListener { _ ->
startSecondActivity()
}
}

override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
Log.d("BackPress", "MainActivity onWindowFocusChanged $hasFocus")
}

override fun onStart() {
super.onStart()
Log.d("BackPress", "MainActivity::onStart")
}

override fun onResume() {
super.onResume()
Log.d("BackPress", "MainActivity::onResume")
}

override fun onPause() {
super.onPause()
Log.d("BackPress", "MainActivity::onPause")
}

override fun onStop() {
super.onStop()
Log.d("BackPress", "MainActivity::onStop")
}

...
}

Aborted back navigation

In this scenario, the back navigation is aborted half way through the animation. As the first activity is visible, it goes through onStart and subsequently through onStop as the back navigation is aborted. Note, even though the first activity is started and its window is visible, its window doesn’t gain focus (onWindowFocusChanged). Apps that have any business logic tied to an Activity’s onStart (like page refresh) would have to account for potential UI changes during back navigation.

// First Activity Launch
MainActivity::onStart
MainActivity::onResume
MainActivity onWindowFocusChanged true

// Second Activity Launch
MainActivity::onPause
MainActivity onWindowFocusChanged false
MainActivity::onStop

// Aborted back Navigation
MainActivity::onStart
MainActivity::onStop
Abort back navigation

Committed back navigation

In this scenario, the back navigation is completed and first activity goes through the following lifecycle. As the first activity is visible, it goes through onStart and subsequently through onResume as the back navigation is completed. Upon resumption, first activity’s window gains focus.

// First Activity Launch
MainActivity::onStart
MainActivity::onResume
MainActivity onWindowFocusChanged true

// Second Activity Launch
MainActivity::onPause
MainActivity onWindowFocusChanged false
MainActivity::onStop

// Completed back Navigation
MainActivity::onStart
MainActivity::onResume
MainActivity onWindowFocusChanged true
Commit back navigation

Summary

Application developers would have to be wary of any activity’s UI logic in onStart (subscribing for updates from ViewModel, Repository, Caches etc) and its UI impact with predictive back navigation, especially as APIs like collectAsStateWithLifecycle and repeatOnLifecycle are either defaulted to or recommended from STARTED state

collectAsStateWithLifecycle
repeatOnLifecycle

--

--