Repository navigation
Introducing Scopes #352
Description
Activity
Special thanks to @ericbottard for listening to my stupid ideas (Rubber duck programming...) and providing a lot of feedback.
One question I haven't answered yet is whether we should use JSR-330
@Injector a custom one.Pros :
- More standard
Cons :
- Requires an extra dependency
- May not play well if integrating with
RoboGuiceorDagger
Extra dependency and intergration woe for only one annotation?
I think would be better to create annotation with diffrent name than@Inject, for example@Wired.@pepyakin interesting. Makes me think of Spring
@Autowired. I was also thinking about using@Injectwith a different package, but then mixing both would need using qualified names.Thanks for portraying me as a duck. I would refrain from using @Inject in a different package, as this would bring much confusion.
@pyricau yep, i kept Spring in mind while thought about
@Wired. But I made it not@Auto...for avoid collision with spring.I think
@Injectin diffrent package might be little bit confusing. For example, if you using auto-complete feature, you can mistakingly import JSR-330 version of@Injectand have unexpectedNullPointerException.Kind of curious @pyricau , what scopes are you planning?
@johncarl81 The basic idea here is that we do not create predefined scopes. Any scope is valid: each new node in the dependency graph is a new scope. This means the injection process will create a defacto scope tree. Then, inside the dependency graph, you're able to attach
@EBeanto a scope from a parent node, which gives it broader visibility.We'll document how to use scope for singletons, activities, fragments... and then anyone could make its own if needed.
Just to be clear, I'm not talking about scopes in the exact sense of Spring or Guice scopes, but more like Module / Container hierarchies. It's an injection time scope.
By the way, I like
@Wired.@pyricau Makes sense... I should have read your initial proposal more closely before commenting ;-)
@RestService(rest service injection) should also be replaced by@Wired.I think it will be better if @Afterviews also 'll be renamed.
Hum.. That's kind of unrelated. What name would use suggest instead of
@AfterViews?Yep, maybe. Just was sleeping when tought about it. As I can see @Afterviews means that the marked method will execute "after views" has been injected. Because it is possible to inject not only views now, it is makes annotation name little bit confusing.
Oh, I see. Well, in fact, we already have a
@AfterInjectannotation :) . Basically, here is what happens:onCreate()is called on the activity subclass.- We inject everything that's not views
- We then call any
@AfterInjectmethod - Then we call
super.onCreate(). - Then we "may" call
setContentView()if a layout is set.
Furthermore, we override
setContentView()to inject views immediately after the content view is set. And after injecting those views and binding the listeners, we call@AfterViewsmethods.This means that any time you call
setContentView()from within your code, view injection will happen again.I'm not sure yet about the whole scope thing. One thing that's still interesting though is the ability to inject fragments, activities, applications etc with the same
@Wiredannotation. The type of the injected element provides enough information (basically its@EXXXannotation) to be able to determine what to do.I gave it a bit more time, and realized this whole thing is quite an over-engineering :) . Let's keep it simple.
I will close this issue, and create new issues for some of the ideas I like in there.
This issue relates to #331, #205, #207 and probably a few others
AndroidAnnotations' current injection model works fine, but it has some drawbacks:
@EBean)@RootContextand view injection / binding will work fine in beans, if a parent bean in the object graph is a singleton. Worst then that, it doesn't fail early, it just skips the injection.I think this comes from the fact that AndroidAnnotations doesn't have any hierarchy of scopes. The basic idea with scopes is that a child scope may access beans from a parent scope, but not the contrary.
I hacked around this idea and came up with a proof of concept: https://github.com/pyricau/androidannotations-scoping . This is a simple eclipse project that doesn't have any dependency on Android / AA, is just simulates the expected behavior.
From a user point of view, here is what the changes would look like :
@RootContext,@Appand@Beanannotations, and replace them all with an@Injectannotation.@EBeanwould take an optionalvalueparameter that would correspond to the scope of this bean. When set, this beans is visible within the whole corresponding scope. For instance, if an A has a dependency on B and C, B and C have a dependency on D, and D is inAscope (@EBean(A.class)), then the same D would be injected in both.Activity, but in fact it can be any class, to fit the user needs.This change will also need to take the specific combination of
@NonConfigurationInstanceand@Beaninto account, and maybe find a new way to reproduce this feature (basically being able to keep bean instances on activity configuration changes).Also note that this change will break backward compatibility quite much. So I think that would be a good opportunity to do other hard changes, such as renaming the packages from
com.googlecode.androidannotations(we're on GitHub now!) toorg.androidannotations, change the maven packages, and introduce AndroidAnnotations 3.0.