Repository navigation
@Parcelable #301
Description
Activity
Thank you Eric for making AndroidAnnotations better :)
I think it's a really good idea to smash a lot of boilerplate android code.
I think we also need a field exclusion mechanism. What do you think about exclude :
- transient fields
- fileds annotated using a new annotation
@NonParcelable
We could also add a validation rule : The class annotated using
@Parcelableshould not implementandroid.os.Parcelablebecause that work is left to the subclass.Hey guys, I saw both of your tweets :) . This is of course a very good idea, but did you notice the Search field on the top of this page ? It's there for a reason ;-) .
Check out #14
😈 😈 😈
Sorry guys: it's my own fault! I was so furious yesterday night to spend so many time to code this stupid parcelable implementation. I'll try to find a solution for issue #14
Hey @pyricau ! You just shatter my dream :'(
Ok guys I have no time this night, but I just wrote some classes to verify how it could / should be done.
I created a gist: https://gist.github.com/3517619
It's quite easy to understand the code:- MyBean and MyChild are my models
- MyBean_ and MyChild_ are the generated classes
- FirstActivity creates a new instance of MyBean and puts the instance into the extras of the intent
- SecondFragment receives the bundle, decodes the parcel and uses MyBean
Et voilà ! Of course there's some code to write to detect the attribute's type and to use the right method to encode / decode the parcel into the generated class.
I tested this solution, and it seems to work fine.
What are you thinking ?- I think you definitely have the right approach to developing new features in AA, which is starting by writing the annotations + generated code before implementing it :) .
- Looks quite good, but I wonder, why did you use a delegate pattern ? Here, you're creating a new
MyBean_instance that is aMyBeanbut delegates everything to anotherMyBeaninstance. This means that you need to create delegation methods fromMyBean_toMyBeanfor all methods ofMyBean. And it's also a bit weird, to create the object twice. - Should we really go for the getter way ? What about have default, protected or public attributes ? For data structures, this can make sense. Should we support both ?
You are absolutely right: this delegate pattern is a nonsense here. I also agree that the getter way is not required: we can only support default, public and protected attributes.
I'll modify the Gist tonight to reflect the changes we were talking about.
Sorry for the delay: I just updated the Gist: https://gist.github.com/3517619
I noticed this line :
aDate = new Date(in.readLong());. Does that mean we should support a standard set of types such asjava.util.Date? If yes, do you know about any other type ?No I think we don't have to support any set of types. In the example I used a Date and I know that a date is - in fact - a long. That's why I parceled it as a long. In my opinion we only have to support the following set of types:
1- primitive (byte, double, float, int, long, String) and primitive arrays
2- Parcelable and Parcelable arrays
3- Bundle
4- SerializableFor the Serializable we could display a warning (if possible) because it is very inefficient.
I read the API documentation about Parcelable and I created a new Gist to show you how we can write parcelables in a more generic way: https://gist.github.com/3643424
writeValue() / readValue() support one of the following types:- null
- String
- Byte
- Short
- Integer
- Long
- Float
- Double
- Boolean
- String[]
- boolean[]
- byte[]
- int[]
- long[]
- Object[](supporting objects of the same type defined here).
- Bundle
- Map (as supported by writeMap(Map)).
- Any object that implements the Parcelable protocol.
- Parcelable[]
- CharSequence (as supported by writeToParcel(CharSequence, Parcel, int)).
- List (as supported by writeList(List)).
- SparseArray (as supported by writeSparseArray(SparseArray)).
- IBinder
- Any object that implements Serializable
Here is the [Parcel doc](http://developer.android.com/reference/android/os/Parcel.html#writeValue(java.lang.Object).
There's a typo in your list : it's not
Object.butObject[](I was a bit surprised at first).So, basically, yeah we can use
writeValue()andreadValue().I worked on this issue this week-end: validators and the processor are done and seem to work - BTW JCodeModel is not really easy to understand and there's not many tutorials or examples on the web.
Now I'd like to add tests in functional-test-1.5 and to test them in functional-test-1.5-tests. Is there any documentation which explain how to do ?
Hi eric,
Thank you for handling that feature development ! And sorry again for the delay...
You're right JCodeModel is not well documented, however AndroidAnnotations source code contains a lot of usage example for this library.
Concerning the tests, there are not documented but once again, we have already wrote a lot of tests and you could just see how they are implemented.
It would be interesting to see if we can take ideas from this : https://github.com/foxykeep/parcelablecodegenerator
@eric-taix did you go further with this? If yes, please let us know the WIP repo so that someone could continue. :)
4 remaining items
I think it's a wonderful idea :)
Since Parceler cannot be integrated because it causes AA to depend on the whole transfuse framework, i started working in our implementation based on @eric-taix's work.
It seems the current implementation just generates the class, and does not take any
EComponentHolderinto account. I think this is not good, because one could want an enhanced component to beParcelable(for example Views are pretty general), it won't work. @DayS what do you think? Can we restrict the usage of this annotation to enhanced components? Or is there any way to use an annotation handler outside of an enhanced component?I think it lacks an annotation to enhance real POJO (object which are not aware of the
Context).
I'd like to have@EBeanfor this kind of object and@EHelperinstead of our current@EBean. But we can't break our API.And what about annotating only the field with
@Parceledfor field we want to be put in the parcel ?
It seems more easy to validate and to process for AA, and to understand for a developer than putting only one annotation for all fields. Then, it's more in the spirit of AA to have an annotation consider only what it's annotating (field, class or method).Actually the current implementation only works with POJOs.
Yeah, it would be more convenient to develop if we would annotate the fields, but it results in more annotations in the code. But how can we create a processor which works on POJOs and enhanced components, too? This would be the new
@EBeanwhat you are talking about?This would be the new @ebean what you are talking about?
Yes, we have to create a
holderfor enhanced POJOs, extendingBaseGeneratedClassHolder. So we need an annotation (starting by E) to declare that the class will be enhanced.
And then, we declare that the class isParcelableby adding@Parcelableon the class or adding@Parceledon the fields.Yeah, it would be more convenient to develop if we would annotate the fields, but it results in more annotations in the code.
I agree, but it also easier to understand for a AA user. Then, private fields won't be parceled (the generated class won't be able to access them). Non parcelable fields either. How do you warn the user about this behaviour ? With an annotation on each field, you can return an error if the field is private or non parcelable.
OK. Unfortunately i do not know AA infrastructure enough to do this change, nor i want to create that, this is too important. Can you implement that sometime?
I'd like to have @ebean for this kind of object and @ehelper instead of our current @ebean. But we can't break our API.
Why not but I'm not sure it worth adding feature. Parcelable could be an exception so if you have any other use case where another root annotation is needed, I'm listening :)
About parcelable, we'll need three annotations :
@EParcelableto enhanced a class and generate parcelable behavior@Parceledto mark a field to be handle by generated parcelable@Parcelableto inject the parcelable object in another enhanced class
The thing is that as
Parcelableis an interface, it shouldn't be responsible for generating the extending class. Indeed, imagine that, in the future, we have another interface likeParcelablethat we want to take into account, let's sayDatabasable. We don't want them to be dependent of each other. So, this way, both will generate an extending class. And we won't be able to use both annotations on the same class.That's why I think that a generating annotation should represent an "extending" relation, not an interface.
LikeEActivitymeans that the class extendsActivity,EServicemeans that the class extendsService,EBeanmeans that the class extendsObjectand has aContext. And I think, it lacks an annotation for a class extendingObjectwithout anyContext. That's why I proposed to renameEBeantoEHelperand add a newEBean.@yDelouis Are you sure we have to break our API? Can't we leave
@EBeanas is and add a new name for theContext-less enhanced class?Of course we can leave
@EBeanas it is.
But I think this name doesn't fit well with what it is.
Any idea for the new enhanced class ?Maybe you are right. If we have an annotation for beans (POJOs), we should not call the annotation for not beans
@EBean. But i think @DayS should make a decision here.BTW i think we should focus are resources. First the current PRs should be finished and merged, i see you already started the plugin-system, etc.
We can't change the behavior of
EBean. It'll be a pain in the ass for every developer using AA as they'll not understand why they don't have context anymore. There are only two options :- find another annotation name for enhanced pojo.
- deprecate
EBean, release the 3.1. reintroduceEBeanwith new behavior and addEHelperthen release 3.2.
But still, I can see all issues about
Ebeannot having context :)Right now, the only names I could think of are :
EUtil,EPojo,EObjectImplemented in #1559.
Implement the Parcelable interface is a waste of time and it's always the same code :
for each attributes to be parceled
get the value
write it (according to its type)
end for
Same kind of code when reading a parcelable
And some glue !
A @parcelable annotation would be really appreciated and will save a lot of time to all of us