-
Notifications
You must be signed in to change notification settings - Fork 114
Scope Resolution
Stéphane Nicolas edited this page May 8, 2016
·
17 revisions
Scope resolution is one of the most important part of ToothPick. It's intuitive in some extent.
The core idea is that scopes are always bubbled up when resolving an injection, and looking up for a binding. Toothpick never goes down the scope tree.
At runtime, when ToothPick will create the injection graph to create an instance of a class and its dependencies, Toothpick will crash if a dependency of this class can't be found in the scope itself or its parent scopes.
Here is an example :
//Example of scopes during the life of an Android application
+----------------------------------------------------------------------------------+ Resolution
| +---------------------------------------------------------------+ | space
| | application scope = @Singleton : | Resolution | for Activity
| | / - Scope --> (application) | space | scope
| | / - IDisplay --> DisplayImpl1 | for @Singleton |
| | / - FooSingleton --> (FooSingleton) | scope |
| +-----/---------------------------------------------------------+ |
| activity scope = @ActivitySingleton : |
| - Scope --> (activity) |
| - IDisplay --> DisplayImpl2 |
| - FooActivitySingleton --> (FooActivitySingleton) |
+----------------------------------------------------------------------------------+
Let's define :
class DisplayImpl1 {@Inject Scope scope}
class DisplayImpl2 {@Inject Scope scope}
@Singleton class FooSingleton {@Inject IDisplay display; @Inject Scope scope}
@ActivitySingleton class FooActivitySingleton {@Inject Scope s; @Inject IDisplay display;}
@Singleton class FooSingletonError {@Inject FooActivitySingleton foo;}
In the table below, we
obj | getInstance(obj, application scope) | getInstance(obj, activity scope) |
---|---|---|
new Scope() | git status | List all new or modified files |
git diff | Show file differences that haven't been staged |
- class
Foo
is not bound to a scope (un-scoped). It can be used in any scope.ToothPick.inject(foo, s)
will always returnfoo.scope = s
. -
FooSingleton
can use an un-scoped dependency such asFoo
.ToothPick.inject(fooSingleton, s)
will always returnfooSingleton.foo.scope = application scope
. -
FooSingleton2
can use a dependency in its own scope. -
FooActivitySingleton
can use an un-scoped dependency such asFoo
.ToothPick.inject(fooActivitySingleton, s)
will always returnfooActivitySingleton.foo.scope = activity scope
. -
FooActivitySingleton2
can use a dependency in its own scope. -
FooActivitySingleton3
can use a dependency in any parent scope of its own scope.ToothPick.inject(fooActivitySingleton, s)
will always returnfooActivitySingleton3.foo.scope = activity scope
but alsofooActivitySingleton3.fooSingleton.scope = application scope
Indeed, there are 2 DAGs in Toothpick :
- the injection dependency relation between classes is oriented (a class
Foo
uses an injected instance of classBar
=class Foo {@Inject Bar}
); - the parent relation between scopes is oriented (an activity scope uses the parent application scope).