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

Conductor - A Fragments Alternative

Conductor - A Fragments Alternative

In order to build truly encapsulated components, one need to use fragments to adhere to the proper lifecycle. There are many pain points when using Fragments. Conductor aims to bring view like simplicity with fragment like flexibility

Yousuf Haque

May 09, 2017
Tweet

More Decks by Yousuf Haque

Other Decks in Programming

Transcript

  1. Conductor
    The misunderstood use case for Fragments, and
    why Conductor fills it perfectly
    Yousuf Haque
    Twitter: @YousufHaque
    Github: yousuf-haque

    View Slide

  2. Nontrivial Apps Need Reusable Views
    - Reuse
    - Layouts
    - View Logic
    - Responsive UIs
    - Encapsulation
    - Loose coupling
    - Ease of testing
    - Sanity

    View Slide

  3. Reusing Views B.F.E. (Before Fragment Era)
    -
    - Pros
    - Good for reusing layouts
    - Cons
    - Can’t reuse programmatically built views
    - Can’t reuse view logic
    - No lifecycle
    - Bottom Line
    - Great for reusing xml layouts that need neither lifecycles nor encapsulation
    - Not enough for “plug and play” components

    View Slide

  4. Reusing Views B.F.E.
    - Custom View Groups and Views
    - Pros
    - Good for reusing layouts, programmatic views, AND view logic
    - Lifecycle: onInflate, onAttachFromWindow, and onDetachFromWindow
    - Enough for “plug and play” components
    - Cons
    - Not enough lifecycle callbacks, need onStop/Start and onResume/Pause
    - GPS or Video playback
    - User status for a chat app
    - BYOBS: No backstack management
    - Bottom Line
    - Great for vast majority of use cases

    View Slide

  5. Surprise: Fragments!

    View Slide

  6. Arrival of Fragments: Pros
    - Fragments arrived in 3.0+
    - Pros
    - Aimed to be like mini activity
    - Contain their own lifecycle methods to have composable UI components with rich,
    encapsulated lifecycle management
    - Fragments are less like reusable views, more like reusable lifecycles
    - Just add water Backstack management
    - Very much “plug and play” philosophy
    - Activity level convenience methods like onActivityResult, and
    onRequestPermissionResult

    View Slide

  7. - Hard to nest (correctly)
    - Key part of building view “atoms”/”plug and play”
    - Children fragments = shenanigans
    - Async Transactions
    - Hard to reason about view state at a given moment
    - commitPendingTransactions is virtually broken
    - Mostly fixed in sdk 24 and support lib 24.0
    - commitNow
    - Children fragment guarantees
    - CommitNow transactions cannot modify
    backstack
    Arrival of Fragments: Cons

    View Slide

  8. - Views + library for backstack
    - Scoop
    - Flow
    - Pancakes
    - Simple-stack
    - Fine for simple lifecycles, still no support for start/stop and resume/pause
    - Need access to activity level items
    - Activity for result
    - Permission handling
    - Can solve with activities implementing interfaces
    - Increases coupling
    Fragment Alternatives

    View Slide

  9. - Basically a wholesale fragments
    replacement
    - Virtually the same API
    - Controllers = Fragments
    - onAttach, onDetach, onCreateView
    - Router = Fragment Manager
    - Router transactions = Fragment
    transactions
    - Has activity level lifecycle methods
    like activityStarted/Stopped and
    resumed/pause
    Enter Conductor

    View Slide

  10. - Built in backstack management
    - Has convenience methods like onActivityResult, and
    onRequestPermissionResult
    - Transactions are done synchronously
    - Controllers survive orientation changes
    - Separate bundles for saving view state on orientation change and controller
    state for process death
    - Composition by default - controllers embody the “plug and play” philosophy:
    compose small, simple controllers into more larger complex ones
    Enter Conductor (continued)

    View Slide

  11. View Slide

  12. - Controller
    - “Atom” of the Conductor world
    - Has its own lifecycle, view, and router
    - Router
    - Applies router transactions
    - Manages backstack
    - RouterTransaction
    - Describes a mutation in UI state
    - A contoller, pushChangeHandler, popChangeHandler
    - A backstack consists of a list of routerTransactions
    - ChangeHandlers
    - Describes animation of controller entering or exiting UI
    - Fade, slide, etc
    Conductor API

    View Slide

  13. View Slide

  14. View Slide

  15. - popCurrentController()
    - pops the topmost controller
    - replaceTopController(transaction : RouterTransaction)
    - replaces the topmost controller with the given transaction
    - popToTag(tag : String)
    - pops all controllers from the top until the tagged controler and its transaction is reached
    - popToRoot()
    - pops all controllers until just the root is left
    - setRoot(transaction : RouterTransaction)
    - sets the given transaction as the root, and clears the back stack if any
    Key Router Methods

    View Slide

  16. - popController(controller: Controller)
    - removes given controller from that router’s backstack, leaving the rest of the backstack in
    tact
    - setRoot(transaction : RouterTransaction)
    - sets the given transaction as the root, and clears the back stack if any
    - setBackStack(transactionList : List)
    - synthesizes a backstack for this router using the specified transactions
    Key Router Methods for Operating on the Backstack

    View Slide

  17. Why should I use Conductor over fragments?
    - Sync/Async
    - Async transactions have a higher surface area for bugs. Router transactions are sync
    - Transaction coupling
    - Fragment transactions couple the new fragment with its eventual container
    - Router transactions can be used by any router
    - Can move responsibility of building transaction elsewhere
    - Controllers are lightweight - everything can be a controller, even small views
    - Surgical backstack management
    - Smaller api + simpler lifecycle -> quicker mastery -> better features, faster
    - View like simplicity with fragment like power; fewer complexities/gotchas

    View Slide

  18. - Won’t it be more difficult to onboard new developers?
    - Simple api to begin with
    - Very similar to fragments
    - Very simple source code to go through
    - Demo app with tons of examples
    - *Conjecture* once the developer is ramped up, a pragmatic and productive API will help the
    team move faster
    Counterpoints

    View Slide

  19. - Not ‘blessed’ by Android Framework
    - "Once we have gotten in to this entry-point to your UI, we really don't care how you organize
    the flow inside. Make it all one activity with manual changes to its views, use fragments (a
    convenience framework we provide) or some other framework, or split it into additional
    internal activities. Or do all three as needed. As long as you are following the high-level
    contact of activity (it launches in the proper state, and saves/restores in the current state), it
    doesn't matter to the system." - Dianne Hackborn Pre IO ‘16 Google+ blog post
    - Fragments are a convenience, not a mandate
    - Conductor is built on views and the activity lifecycle (and a headless
    fragment)
    Counterpoints

    View Slide

  20. - https://github.com/bluelinelabs/Conductor
    - https://www.youtube.com/watch?v=k3IT-IJ0J98
    - https://medium.com/square-corner-blog/advocating-against-android-fragm
    ents-81fd0b462c97
    Resources

    View Slide