Feature Request: component introspection based on a base class/interface
See original GitHub issueI’m working on setting up the graph architecture in my application (Twitter for Android), and I ran into the problem of cleaning up scoped bindings when a Dagger component is discarded.
Let’s say that I inject a user database from a scoped Dagger component. Dagger takes care of creating an instance of my database when first requested, and injecting it to all clients of the dependency. No one client owns the database object itself, so the responsibility of closing it when discarding the component is not clearly assigned. Extracting from the component all references that require cleanup, however, poses several issues:
- Exposing all bindings that require cleanup through provision methods in the component is undesirable, since it forces me to publish bindings that should remain private. Also, it’s error-prone, since it requires me to write the cleanup code to call each method explicitly.
- Getting an object for cleanup would create it if it was uninitialized.
I have addressed the first issue by providing objects that require cleanup to a multibound set, and putting a bunch of lint rules in place to detect omissions. This works, but it’s clunky and verbose. I don’t have a good solution for the second problem.
Taking a step back, it seems to me that this is a particular case of the larger problem of extracting objects from a component based on properties like base classes or implemented interfaces. Ideally, I would like to be able to declare such a multibinding as this:
@Multibindings
interface MyMultibindings {
@NotNull
@InstancesOf(type = Closeable.class, transitive = false, onlyIfInitialized = true)
Set<Closeable> closeables();
}
I threw in a couple of flags that would make this feature more generally useful:
- transitive, for configuring whether the multibinding should include nesting scopes.
- onlyIfInitialized, to select all providers or only those in the initialized state.
Incidentally, this would be particularly useful if Dagger’s scoped providers would expose the functionality to query and update their state, since that may be used to release providers on demand while doing the proper cleanup (which doesn’t seem to be available in the Releasable References API).
Would this make sense in the overall design of Dagger? Do you have an alternative solution for this kind of problem?
Issue Analytics
- State:
- Created 7 years ago
- Reactions:1
- Comments:8
Top GitHub Comments
Firstly, we’re working on an API to make it easier to your own additional static analysis on the graph. Hopefully that’ll help to make sure people don’t slip up (and that your checks are accurate).
We’re discussing the idea of providing features for closing resources within Dagger. To help me understand: do you want to group bindings that you want closed all at once, or do you want this at the individual binding level?
There are definitely some manual ways of doing this:
Is that similar to what you were thinking about?
Closing since, in hindsight, injecting
Closer
or similar event notifier explicitly does sound like a better option.