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

Toothpick: a fresh approach to Dependency Injection (DI) on Android.

Toothpick: a fresh approach to Dependency Injection (DI) on Android.

You find RoboGuice simple but slow ? And you think Dagger 1 & 2 are fast but complex and bloated ? Toothpick is the best of both worlds !
Toothpick is a scope tree based, runtime but reflection free implementation of JSR 330. It is pure Java, with a special focus on Android.
Toothpick is fast (even faster than Dagger 2 in some cases!) and is simpler to use, with less boilerplate code. Its syntax is very close to Guice. It supports named dependencies, lazy dependencies, providers, and has built-in support for custom scopes. As compared to Dagger 2, Toothpick provides more powerful testing support, allowing you to leverage DI to mock dependencies using either mockito or easymock.
Its explicit scope tree helps developers to build more robust apps. It provides more fine grained control to easily implement complex user flows that span multiple activities or state preservation across configuration changes (e.g. rotations), a common issue when implementing the MVP pattern.
During this talk for experts, we will introduce Toothpick, its main features and how it compares to other DI libs. We will explain how Toothpick scopes and scope annotations can solve advanced use cases when developing Android apps.
Prerequisites: DI on Android, testing, mocking, memory leaks.

stephanenicolas

June 24, 2016
Tweet

More Decks by stephanenicolas

Other Decks in Programming

Transcript

  1. Toothpick: 

    scope tree 

    Dependency Injection
    https://github.com/stephanenicolas/toothpick

    View Slide

  2. 2/40
    About us
    Stéphane Nicolas
    Senior Android Dev at
    Groupon
    stephanenicolas
    snicolas
    +stephane nicolas
    Daniel Molinero
    Android Dev at
    Groupon
    dlemures
    +DaniLemures
    @D_Lemures

    View Slide

  3. Groupon Android Team is Hiring
    https://jobs.groupon.com/#/categories/engineering

    View Slide

  4. 4/40
    Toothpick
    What is Toothpick?
    • Scope tree based Dependency Injection library
    • Full featured implementation of the JSR 330
    • Runtime based, but does not use reflection. Replaced
    by annotation processing
    • Almost as fast as Dagger, even faster in some cases
    • As simple as Roboguice, with few rules
    • Advanced testing support

    View Slide

  5. • Introduction
    • TP Vs Daggers: Even sharper !
    • Toothpick Features
    • Basic Injections
    • Scope Tree of an Android App
    • Configurations
    • Testing
    • Flows & Scopes
    • Conclusion
    Plan
    5/40

    View Slide

  6. Roboguice - Runtime time DI
    • friendly syntax, simple
    • too slow (uses reflection)
    • too big (dex methods count & APK size)
    Why Toothpick ?
    Daggers - Compile time DI
    • Fast !
    • tough syntax. Hard to use & maintain
    • No easy testing
    6/40

    View Slide

  7. 7/40
    Why Toothpick ?
    Ease of
    use
    Speed
    Roboguice
    Dagger
    Toothpick
    Best of both worlds

    View Slide

  8. 8/40
    Toothpick Vs. Daggers
    Speed comparison

    View Slide

  9. 9/40
    Toothpick Vs. Daggers
    1000 injections
    • Dagger 1: 33 ms
    • Dagger 2: 31 ms
    • Toothpick: 35 ms
    6400 injections
    • Dagger 1: 45 ms
    • Dagger 2: 42 ms
    • Toothpick: 66 ms
    Speed comparison in a reasonable range
    TODO redo the
    graph for 0
    injection

    View Slide

  10. 10/40
    Toothpick Vs. Daggers
    Ease of use
    TP gains over Dagger 2:
    • Lines of Code:
    • No need for component interfaces
    • No special rules to passover stuff to sub-
    components
    • More flexible use of field / constructor injections
    • Less rules to learn, easier to use.

    View Slide

  11. Dependencies?
    • Snow Cone Machine.
    • Dependencies: Ice Machine + Syrup Dispenser
    11/40
    Basic Injection

    View Slide

  12. Snow Cone Machine
    • Dependencies: Ice Machine + Syrup Dispenser
    12/40
    Basic Injection

    View Slide

  13. Basic Injection : @Inject
    Snow Cone Machine
    • Dependencies: Ice Machine + Syrup Dispenser
    13/40
    Specify
    Dependencies
    SnowConeMachine uses @Inject to specify its dependencies.
    It can use Lazy to lazily create some dependencies.

    View Slide

  14. Basic Injection : Scopes
    14/40
    Scope
    Instance creations take place inside scopes
    SnowConeMachine
    IceMachine
    SyrupDispenser
    All dependencies of the SnowConeMachine are injected.

    Transitively, all dependencies of the dependencies are
    created as well…

    View Slide

  15. Basic Injection : Scopes
    15/40
    Scope
    Injections take place inside scopes
    When we don’t have control on the creation of an entry
    point, we can inject its fields inside a scope. It will also
    create transitively all dependencies.

    View Slide

  16. Basic Injection : Scopes & Bindings
    16/40
    Scope
    Scopes contain bindings.
    Bindings are configured via modules.

    IceMachine’s instance is a singleton of this scope.
    Module
    1
    Module
    2
    IceMachine —> new IceMachine
    SyrupDispenser —> LemonSyrupDispenser

    View Slide

  17. Basic Injection : Scopes & Bindings
    17/40
    Bindings describe what is to be injected.

    Bindings can recycle instances → Singletons.
    SnowConeMachine
    IceMachine
    Lemon

    SyrupDispenser

    View Slide

  18. 18/40
    Scope annotations
    • The Ice Machine is a Singleton
    • Use @Singleton annotation or a module
    =
    Scope
    IceMachine

    —> new IceMachine
    =

    View Slide

  19. 19/40
    Scope annotations
    TODO custom
    scope annotations.
    Present singleton
    as a special case.

    View Slide

  20. Scope tree of an Android App
    20/40
    Application
    MakeLemonCones

    Activity
    MakeAppleCones

    Activity
    SyrupDispenser

    —> LemonSyrupDispenser
    SyrupDispenser

    —> AppleSyrupDispenser
    IceMachine

    —> new IceMachine
    IceMachine is a Singleton at the App level.
    SyrupDispenser is bound to different implementations
    in each activity scope.

    View Slide

  21. Scope tree of an Android App
    21/40
    Application
    IceMachine

    —> new IceMachine

    View Slide

  22. Scope tree of an Android App
    22/40
    Application
    MakeLemonCones

    Activity
    When opening multiple scopes at the same time, 

    they will be children from each other, in left to right order.
    The last child scope is returned.

    View Slide

  23. 23/40
    Toothpick Modules
    2 Snow Cone Machines: Lemon and Apple
    Each activity will define its own scopes, that
    defines different bindings

    View Slide

  24. Scope tree of an Android App
    24/40
    Application
    Activity
    2
    TP scope tree is totally extensible. It can be printed at anytime.
    Activity
    1
    Fragment
    2
    View
    1
    Fragment
    1
    Service
    2
    Service
    1

    View Slide

  25. Configurations
    25/40
    TODO slide with all
    possible
    configurations

    View Slide

  26. Configurations
    26/40
    TODO slide to
    explain registries

    View Slide

  27. Configurations
    27/40
    Performance of Registries Vs. Reflection

    View Slide

  28. Testing: simple tests
    28/40

    View Slide

  29. Testing: simple tests
    29/40
    Chain
    Junit4

    rules Prepare m
    ocks 

    &
    stuff under test
    Enjoy

    View Slide

  30. Testing: even simpler tests
    30/40

    View Slide

  31. Testing: Robolectric tests
    31/40

    View Slide

  32. 32/40
    Chain
    Junit4

    rules
    override activity scope
    with
    m
    ocks from
    TP
    Testing: Robolectric tests

    View Slide

  33. Testing
    33/40
    Application
    MakeLemonCones

    Activity
    Toothpick testing offers:
    • both mockito and easymock
    support
    • create mocks with annotations
    • creates any scope and binds
    mocks into the scope
    • create instances and injects on
    demand
    your mocks go here

    View Slide

  34. Flows and scopes: MVP
    34/40
    Custom
    scope
    Application
    Activity 1
    Activity 1
    MVP, keeping the presenter state
    • Nowadays → Retained fragments, 

    Loaders, etc.
    • Toothpick → Use a scope to retain 

    the instance of the Presenter

    View Slide

  35. Flows and scopes: MVP
    35/40
    Custom scopes:
    • are not related to life cycle of
    objects
    • can be associated with a scope
    annotation
    • an annotated dependency will be
    created in this custom scope
    • allow to persist state across
    rotations
    • can span across multiple
    activities (user flows)
    Custom
    scope
    Activity 2
    Application
    Activity 1
    Activity 1

    View Slide

  36. Flows and scopes: MVP
    36/40
    Define a depedency
    Create a custom 

    scope annotation
    Annotate a 

    dependency
    to make it a 

    singleton of a 

    custom scope

    View Slide

  37. Flows and scopes: MVP
    37/40
    Presenter

    Scope
    Application
    Activity 1

    View Slide

  38. Flows and scopes: MVP
    38/40
    Close
    the scope

    of the activity
    as it dies
    Close the presenter

    scope as you
    leave this flow
    App
    Presenter
    Activity

    View Slide

  39. Flows and scopes: MVP
    39/40
    User flow
    scope
    Activity 3
    Application
    Activity 1
    • User flow data
    • Nowadays -> Send data over
    and over through Intents,
    Database, …
    • Toothpick -> Use a common
    scope for the whole flow to
    keep flow related data
    • The data will be garbage
    collected as you close the
    scope when leaving the flow
    Activity 2

    View Slide

  40. 40/40
    Conclusion
    • Toothpick is scope tree based DI framework
    • Fast and simple
    • Advanced testing support
    • Offers nice advanced scenarios: 

    Presenter scope, User Flow Scope, etc.
    Comments // Questions ?

    View Slide