Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Android App Architecture & Navigation

Bryan Herbst
September 04, 2018

Android App Architecture & Navigation

A look into the new navigation architecture component and how it fits with Fragments and Activites

Bryan Herbst

September 04, 2018
Tweet

More Decks by Bryan Herbst

Other Decks in Technology

Transcript

  1. Android App
    Architecture
    & Navigation
    Bryan Herbst
    (@bryancherbst)

    View Slide

  2. Activities
    &
    Fragments

    View Slide

  3. STOP

    View Slide

  4. STOP
    If you like what you have, keep it

    View Slide

  5. When to use what?

    View Slide

  6. Where we’ve been

    View Slide

  7. In the beginning
    there was Activity

    View Slide

  8. Activity
    Entry point to your application

    View Slide

  9. Activity
    Entry point to your application
    Has a Window

    View Slide

  10. Activity
    Entry point to your application
    Has a Window
    Has a lifecycle

    View Slide

  11. Activity
    Entry point to your application
    Has a Window
    Has a lifecycle
    Responds to configuration changes

    View Slide

  12. Activity
    Entry point to your application
    Has a Window
    Has a lifecycle
    Responds to configuration changes
    ActivityManager handles back stack

    View Slide

  13. Activity
    Layout inflation
    View manipulation
    Click handlers
    Animations
    Navigation
    Menu creation
    Menu item callbacks
    Database calls
    Networking calls
    Disk I/O
    Sensor input
    Geolocation

    View Slide

  14. Activity
    Window transitions can be difficult
    !

    View Slide

  15. Activity
    Window transitions can be difficult
    A lot of plumbing
    !

    View Slide

  16. Activity
    Window transitions can be difficult
    A lot of plumbing
    Nuanced (and limited) backstack
    !

    View Slide

  17. Enter Honeycomb (3.0)

    View Slide

  18. View Slide

  19. Fragments!

    View Slide

  20. Fragment
    Has lifecycle (less than Activity)

    View Slide

  21. Fragment
    Has lifecycle (less than Activity)
    Backstack via FragmentManager

    View Slide

  22. Fragment
    Has lifecycle (less than Activity)
    Backstack via FragmentManager
    Composable

    View Slide

  23. Fragment
    Has lifecycle (less than Activity)
    Backstack via FragmentManager
    Composable
    Belong to an Activity

    View Slide

  24. Fragments
    Transactions are annoying
    !

    View Slide

  25. Fragments
    Transactions are annoying
    Lifecycles are annoying
    !

    View Slide

  26. Fragments
    Transactions are annoying
    Lifecycles are annoying
    Can still be too big
    !

    View Slide

  27. Fragments
    Transactions are annoying
    Lifecycles are annoying
    Can still be too big
    Bugs
    !

    View Slide

  28. Fragments
    Transactions are annoying
    Lifecycles are annoying
    Can still be too big
    Bugs
    Differences from Activity
    !

    View Slide

  29. Meanwhile

    View Slide

  30. View-based
    architecture

    View Slide

  31. View
    Draws things
    Reacts to user interaction

    View Slide

  32. View
    Almost no lifecycle
    No backstack
    !

    View Slide

  33. Where are we now?

    View Slide

  34. Single activity app
    Easier to manage transitions

    View Slide

  35. Single activity app
    Easier to manage transitions
    Composable UI elements

    View Slide

  36. Single activity app
    Easier to manage transitions
    Composable UI elements
    Google can be opinionated

    View Slide

  37. Don’t like lifecyles?
    Use Lifecycle

    View Slide

  38. class MainActivity : Activity {
    override fun onStart() {
    super.onStart()
    analytics.reportStart()
    }
    }

    View Slide

  39. activity.lifecycle
    .addObserver(AnalyticsObserver())
    class AnalyticsObserver : LifecycleObserver {
    @OnLifecycleEvent(ON_START)
    fun trackPageLoad() {
    analytics.reportStart()
    }
    }

    View Slide

  40. activity.lifecycle
    .addObserver(AnalyticsObserver())
    class AnalyticsObserver : LifecycleObserver {
    @OnLifecycleEvent(ON_START)
    fun trackPageLoad() {
    analytics.reportStart()
    }
    }

    View Slide

  41. Fragment refresher

    View Slide

  42. Which Fragments?
    Framework fragments
    Support fragments

    View Slide

  43. Which Fragments?
    Framework fragments
    Support fragments
    !
    "

    View Slide

  44. Fragment transactions

    View Slide

  45. Fragment transactions
    fragmentManager.beginTransaction()

    View Slide

  46. Fragment transactions
    fragmentManager.beginTransaction()
    .add()

    View Slide

  47. Fragment transactions
    fragmentManager.beginTransaction()
    .remove()

    View Slide

  48. Fragment transactions
    fragmentManager.beginTransaction()
    .replace()

    View Slide

  49. Fragment transactions
    fragmentManager.beginTransaction()
    .show()

    View Slide

  50. Fragment transactions
    fragmentManager.beginTransaction()
    .hide()

    View Slide

  51. Fragment transactions
    fragmentManager.beginTransaction()
    .addToBackstack()

    View Slide

  52. Fragment transactions
    fragmentManager.beginTransaction()
    .commit()

    View Slide

  53. Fragment transactions
    fragmentManager.beginTransaction()
    .add()
    .replace()
    .hide()
    .addToBackstack()
    .commit()

    View Slide

  54. Transactions are
    asynchronous

    View Slide

  55. The IllegalStateException
    com.awesomeapp E/MainActivity:
    java.lang.IllegalStateException:
    Cannot perform this action
    after onSaveInstanceState

    View Slide

  56. The IllegalStateException
    FM State

    View Slide

  57. The IllegalStateException
    FM State
    add()

    View Slide

  58. The IllegalStateException
    FM State
    add()

    View Slide

  59. The IllegalStateException
    FM State
    add()
    hide()

    View Slide

  60. The IllegalStateException
    FM State
    add()
    hide()
    onStop()!!

    View Slide

  61. The IllegalStateException
    FM State
    add()
    hide()
    onStop()!!
    Persisted
    add()
    hide()

    View Slide

  62. The IllegalStateException
    FM State
    onStart()
    Persisted
    add()
    hide()

    View Slide

  63. The IllegalStateException
    FM State
    add()
    hide()
    Persisted
    add()
    hide()
    replace()

    View Slide

  64. The IllegalStateException
    After onSaveInstanceState
    any future changes
    may be lost

    View Slide

  65. Okay, but async
    transactions suck

    View Slide

  66. Commit()
    commit()
    executePendingTransactions()
    commitAllowingStateLoss()
    commitNow()
    commitNowAllowingStateLoss()

    View Slide

  67. Commit()
    commit()
    executePendingTransactions()
    commitAllowingStateLoss()
    commitNow()
    commitNowAllowingStateLoss()

    View Slide

  68. Commit()
    commit()
    executePendingTransactions()
    commitAllowingStateLoss()
    commitNow()
    commitNowAllowingStateLoss()

    View Slide

  69. Commit()
    commit()
    executePendingTransactions()
    commitAllowingStateLoss()
    commitNow()
    commitNowAllowingStateLoss()

    View Slide

  70. Back stack
    addToBackStack(null)

    View Slide

  71. Back stack
    popBackStack()

    View Slide

  72. Back stack
    addToBackStack("screenA")

    View Slide

  73. Back stack
    addToBackStack("screenA")

    View Slide

  74. Back stack
    addToBackStack("screenB")

    View Slide

  75. Back stack
    addToBackStack("screenC")

    View Slide

  76. Back stack
    popBackStack("screenA", 0)

    View Slide

  77. But that’s
    a lot of work

    View Slide

  78. Navigation

    View Slide

  79. Navigation Challenges
    Transitions

    View Slide

  80. Navigation Challenges
    Transitions
    Back stack management

    View Slide

  81. Navigation Challenges
    Transitions
    Back stack management
    Up vs. back

    View Slide

  82. Navigation Challenges
    Transitions
    Back stack management
    Up vs. back
    Passing data

    View Slide

  83. Navigation Challenges
    Transitions
    Back stack management
    Up vs. back
    Passing data
    Deep linking

    View Slide

  84. Android Jetpack:
    Navigation

    View Slide

  85. Principles
    Navigation is a stack

    View Slide

  86. Principles
    Navigation is a stack
    Up never exits the app

    View Slide

  87. Principles
    Navigation is a stack
    Up never exits the app
    Up = Back within your app

    View Slide

  88. Principles
    Navigation is a stack
    Up never exits the app
    Up = Back within your app
    Deep linking should yield the same stack

    View Slide

  89. Navigation (the library)

    View Slide

  90. Navigation library
    No more Fragment transactions!

    View Slide

  91. Navigation library
    No more Fragment transactions!
    No more startActivity()!

    View Slide

  92. Navigation library
    No more Fragment transactions!
    No more startActivity()!
    Just call navigate()

    View Slide

  93. Navigation Graph
    All the destinations in your app,
    plus the action that connect
    them.

    View Slide

  94. Navigation Graph
    New XML resource type!

    View Slide

  95. Navigation tooling

    View Slide

  96. Navigator
    What destination types are
    available?

    View Slide

  97. NavHost
    Where do those destinations
    reside?

    View Slide

  98. NavController
    How do I get there?

    View Slide

  99. Current Navigators
    ActivityNavigator

    View Slide

  100. Current Navigators
    ActivityNavigator
    FragmentNavigator

    View Slide

  101. android:id="@+id/navHost"
    android:name=
    "androidx.navigation.fragment.NavHostFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:defaultNavHost="true"
    app:navGraph="@navigation/nav_graph" />

    View Slide

  102. android:id="@+id/navHost"
    android:name=
    "androidx.navigation.fragment.NavHostFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:defaultNavHost="true"
    app:navGraph="@navigation/nav_graph" />

    View Slide

  103. Do the navigation
    Navigation
    .findNavController(view)
    .navigate(R.id.action_id)

    View Slide

  104. Destinations: Deep link
    Destinations can have deep links
    android:id="@+id/home”
    android:name="com.example.HomeFragment"
    android:label="fragment_home">


    View Slide

  105. Actions: Animations
    Actions can have transition animations
    app:destination="@id/detail"
    app:popEnterAnim="@anim/slide_in_left"
    app:popExitAnim="@anim/slide_out_right"
    app:enterAnim="@anim/slide_in_right"
    app:exitAnim="@anim/slide_out_left"/>

    View Slide

  106. Actions: back stack
    Each action can define its own behavior
    android:id="@+id/home_to_details"
    app:destination="@id/details”
    app:popUpTo="@id/splash”
    app:popUpToInclusive="false" />

    View Slide

  107. Arguments
    Actions can all have arguments

    android:name="name"
    android:defaultValue="Joe" />

    View Slide

  108. Arguments
    Works with deep links!

    android:name="name"
    android:defaultValue="Joe" />


    View Slide

  109. Safeargs
    androidx.navigation.safeargs

    View Slide

  110. Safeargs
    androidx.navigation.safeargs
    Generates argument wrapper classes

    View Slide

  111. Safeargs
    Demo time!

    View Slide

  112. Demo time!

    View Slide

  113. Custom destination
    You can make your own Navigator!

    View Slide

  114. What’s missing
    Some integration with common elements
    like bottom navigation

    View Slide

  115. What’s missing
    Some integration with common elements
    like bottom navigation
    Shared element transitions

    View Slide

  116. What’s missing
    Some integration with common elements
    like bottom navigation
    Shared element transitions
    Nested navigation graphs

    View Slide

  117. What’s missing
    Some integration with common elements
    like bottom navigation
    Shared element transitions
    Nested navigation graphs
    Result data (e.g. startActivityForResult())

    View Slide

  118. What if I want to
    migrate to Navigation?

    View Slide

  119. I currently have…

    View Slide

  120. Single Activity

    View Slide

  121. Single Activity
    Set up navigation graph

    View Slide

  122. Single Activity
    Set up navigation graph
    Each Fragment is a destination

    View Slide

  123. Single Activity
    Set up navigation graph
    Each Fragment is a destination
    Every transaction is an action

    View Slide

  124. Single Activity
    Set up navigation graph
    Each Fragment is a destination
    Every transaction is an action
    Define arguments

    View Slide

  125. Single Activity
    Set up navigation graph
    Each Fragment is a destination
    Every transaction is an action
    Define arguments
    Replace transactions with
    NavController.navigate()

    View Slide

  126. Multiple activities
    Start by making a graph for each Activity

    View Slide

  127. Multiple activities
    Start by making a graph for each Activity
    If you want a single Activity,
    combine Activities one screen at a time

    View Slide

  128. Activity Chrome

    View Slide

  129. Activity Chrome
    CoordinatorLayout
    .setStatusBarBackgroundColor()

    View Slide

  130. Activity Features
    android:name=".MainActivity"
    android:windowSoftInputMode="adjustPan" />

    View Slide

  131. Activity Features
    android:name=".MainActivity"
    android:windowSoftInputMode="adjustPan" />
    activity.window
    .setSoftInputMode(SOFT_INPUT_ADJUST_PAN)

    View Slide

  132. More complex
    Watch for updates!
    Provide feedback!

    View Slide

  133. Resources
    https://developer.android.com
    /topic
    /libraries
    /architecture
    /navigation

    View Slide