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
- 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
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
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 “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
- 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
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
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)
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
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
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<RouterTransaction>) - synthesizes a backstack for this router using the specified transactions Key Router Methods for Operating on the Backstack
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
- 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
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