You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
Repository navigation
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
As much as we love using AA, we don't like referencing enhanced classes (or _classes) in our code.
First because it's not architecturally pleasing.
And second because when the AA generation fails, you have to remove all the imports that reference the enhanced classes before AA generation can start again.
Which is always a pain.
Referencing the enhanced class
The truth is AA helps to avoid referencing the enhanced components via the @Bean, @FragmentById, @App annotations.
Nevertheless, there are still use cases when you have to invoke enhancing classes in your code (and have an added import clause):
One. when you start an EActivity
startActivity(newIntent(this, MyActivity_.class));
// Or better (thanks @WonderCsabo)MyActivity_.intent(this).start() ;
Two. when you use an EGroupView in your ListAdapter
The idea is to create a new class Factory (or CreatorFacade as @jeremiemartinez named it) in androidannotations-api.jar.
Creator_ classes will be generated for each enhanced classes and will register at the application startup to the Factory.addCreator().
The factory will be available everywhere in the code:
Well, as I said @jeremiemartinez and @fredszaq laid out the path for us. Their branch work and demonstrate the whole idea.
For the moment, it works only EBean. EFragment, EView and EGroupView should be added.
And the best thing is that that solution doesn't use reflection. At all.
Please note that @Pref is another issue: the methods in the interface and the generated class are not matching (PrefField vs. the relevant Java type) hence the generated class cannot implement the interface. But there is a plan to change this.
Also we should not create Intents, let AAs IntentBulder do that.
I agree. I really do not like to use generated class names in my code. You are right about that EFragment, EView and EGroupView are also suffering from this issue. @DayS, @yDelouis WDYT?
To register Creators at application startup, we need to add an annotation on the Application class for each enhanced class, which I don't like so much.
Then, I don't like to put data in static attributes because they can be garbage collected if memory is needed. And if we put the creators in the application instance, we won't be able to retrieve it from the Factory class.
And EBeanCreator is an interface present in the API jar :
publicinterfaceEBeanCreator<T> {
Tcreate();
}
Some other interfaces would exist for Activities, Services, Fragments, Views, etc...
About the naming, I hesitate between Creator and Factory. I prefer Factory because it seems more generic. But, I put Creator in the examples because these interfaces look more like the Creator class of PerfectCarl's proposition.
Maybe it's not used that often( I personally don't) but it was the bread and butter (as far as I understood) of the original contribution.
To register Creators at application startup, we need to add an annotation on the Application
class for each enhanced class, which I don't like so much.
I, too, don't like it very much.
Note that you can also do this:
So there will be only one Creator in your whole application.
Still you have to register all the enhanced components that you are willing to create via the CreatorFacade, but it feels prettier.
As a rule, I resent that apt doen't let us register somehow a bunch of interesting/annotated classes after the code generation is done.
Your solution deals with that elegantly and clearly states the dependency between your class and the enhanced component.
Then, I don't like to put data in static attributes because they can be garbage collected
if memory is needed.
Good point.
And if we put the creators in the application instance, we won't be able to retrieve it from
the Factory class.
What do you mean?
Last point, how would you create intents for your EActivity ?
Is there a need for Activity, Fragment, Bean ... specific interface?
Besides, I would suggest to add a method to retreive the class
@WonderCsabo, I wanted to write what I wrote. I meant that static attributes can be reset if the application is killed. And even if it will be initialized again when the application restarts, I think it's not a good pattern in Android to have static singletons.
But it seems a bit strange to me to write this because you'd just have to annotate your class Utils with @EBean.
So there will be only one Creator in your whole application.
Still you have to register all the enhanced components that you are willing to create via the CreatorFacade, but it feels prettier.
I don't like to put too much things in the Application and that Activities, Fragments or Services depend on the application object. I like to keep things small and that classes does not know more than the things they are responsible for. A bean shouldn't know the application in which it lives, a view shouldn't know about the activity is embed in.
As a rule, I resent that apt doesn't let us register somehow a bunch of interesting/annotated classes after the code generation is done.
Annotation processing works this way to enable incremental build. And there is no way around this.
And if we put the creators in the application instance, we won't be able to retrieve it from
the Factory class.
What do you mean?
In the Factory, you'll have to write something like this :
But this class will be in the annotation api jar and won't know what class to cast applicationContext to.
Last point, how would you create intents for your EActivity ?
The interface ActivityCreator would have a method which returns an ActivityIntentBuilder (added by PR #994). We still have a problem with extras. This comment could help us.
Is there a need for Activity, Fragment, Bean ... specific interface?
The answer is given above. For Bean, the Creator would return the instance directly but for Activity, it would return an ActivityIntentBuilder and for Fragment, a FragmentBuilder.
Besides, I would suggest to add a method to retrieve the class
I don't like to put too much things in the Application and that Activities, Fragments or Services depend on the application object. ...
Me neither. You are making a very strong point here.
The interface ActivityCreator would have a method which returns an ActivityIntentBuilder
...
The answer is given above. For Bean, the Creator would return the instance directly but for Activity, it would return an ActivityIntentBuilder and for Fragment, a FragmentBuilder.
Using the builder classes, the proposed interfaces could be (names are just for information):
If the interface EActivityCreator returns the generic ActivityIntentBuilder instead of the MyActivityIntentBuilder_ it might be convient to add a ActivityIntentBuilder.start(Bundle) to provide extra data to the intent in a generic (albeit not type safe) way.
Then we can have case four, not rely on static fields.
Of course, we'd still use the Application as the singleton that it is, but this is just an implementation detail...
Activity
WonderCsabo commentedon May 30, 2014
Please note that
@Prefis another issue: the methods in the interface and the generated class are not matching (PrefFieldvs. the relevant Java type) hence the generated class cannot implement the interface. But there is a plan to change this.Also we should not create
Intents, let AAsIntentBulderdo that.WonderCsabo commentedon May 30, 2014
I agree. I really do not like to use generated class names in my code. You are right about that EFragment, EView and EGroupView are also suffering from this issue. @DayS, @yDelouis WDYT?
yDelouis commentedon May 30, 2014
Comments
To register
Creators at application startup, we need to add an annotation on theApplicationclass for each enhanced class, which I don't like so much.Then, I don't like to put data in static attributes because they can be garbage collected if memory is needed. And if we put the creators in the application instance, we won't be able to retrieve it from the
Factoryclass.Another proposition
The developer would write something like this :
The example is with
EActivityandEBeanbut will work with all enhanced class.And the generated code will look like this :
And
EBeanCreatoris an interface present in the API jar :Some other interfaces would exist for
Activities,Services,Fragments,Views, etc...About the naming, I hesitate between
CreatorandFactory. I preferFactorybecause it seems more generic. But, I putCreatorin the examples because these interfaces look more like theCreatorclass of PerfectCarl's proposition.PerfectCarl commentedon May 31, 2014
@yDelouis
I like your proposition but the case four is left behind
Maybe it's not used that often( I personally don't) but it was the bread and butter (as far as I understood) of the original contribution.
I, too, don't like it very much.
Note that you can also do this:
So there will be only one Creator in your whole application.
Still you have to register all the enhanced components that you are willing to create via the
CreatorFacade, but it feels prettier.As a rule, I resent that apt doen't let us register somehow a bunch of interesting/annotated classes after the code generation is done.
Your solution deals with that elegantly and clearly states the dependency between your class and the enhanced component.
Good point.
What do you mean?
Last point, how would you create intents for your EActivity ?
Is there a need for Activity, Fragment, Bean ... specific interface?
Besides, I would suggest to add a method to retreive the class
PerfectCarl commentedon May 31, 2014
@WonderCsabo
Agreed but I aimed at being comprehensive. Listing cases that would be excluded from that suggestion (like case 3 and 5)
Thanks for the reminder about
IntentBuilderWonderCsabo commentedon May 31, 2014
I think he wanted to write:
yDelouis commentedon May 31, 2014
@WonderCsabo, I wanted to write what I wrote. I meant that static attributes can be reset if the application is killed. And even if it will be initialized again when the application restarts, I think it's not a good pattern in Android to have static singletons.
@PerfectCarl,
For this case, you could inject a creator in the custom
Applicationand write something like this :But it seems a bit strange to me to write this because you'd just have to annotate your class
Utilswith@EBean.I don't like to put too much things in the
Applicationand thatActivities,FragmentsorServicesdepend on the application object. I like to keep things small and that classes does not know more than the things they are responsible for. A bean shouldn't know the application in which it lives, a view shouldn't know about the activity is embed in.Annotation processing works this way to enable incremental build. And there is no way around this.
In the
Factory, you'll have to write something like this :But this class will be in the annotation api jar and won't know what class to cast applicationContext to.
The interface
ActivityCreatorwould have a method which returns anActivityIntentBuilder(added by PR #994). We still have a problem with extras. This comment could help us.The answer is given above. For
Bean, theCreatorwould return the instance directly but forActivity, it would return anActivityIntentBuilderand forFragment, aFragmentBuilder.+1
PerfectCarl commentedon May 31, 2014
Me neither. You are making a very strong point here.
Using the builder classes, the proposed interfaces could be (names are just for information):
If the interface
EActivityCreatorreturns the genericActivityIntentBuilderinstead of theMyActivityIntentBuilder_it might be convient to add aActivityIntentBuilder.start(Bundle)to provide extra data to the intent in a generic (albeit not type safe) way.PerfectCarl commentedon Jun 1, 2014
I was re-reading
Well to be fair there is a way to implement the
Factorybased on the enhanced application.Have
MyApplication_implementsFactoryApplicationand write the following code then
Then we can have case four, not rely on static fields.
Of course, we'd still use the Application as the singleton that it is, but this is just an implementation detail...
gauravsak commentedon Dec 30, 2016
@WonderCsabo @PerfectCarl @yDelouis What is the current status of this issue? There hasn't been an update for a while. Thanks!