Search code examples
androidparcelableandroid-annotationsparceler

Use Android Annotations with Parceler


I'm using Android Annotations in my Android Project. As implementing Parcelable is a lot of work I want to use Parceler and the @Parcel annotation.

The problem is that if I want to use the @FragmentArg annotation by Android Annotations it doesn't (for obvious reasons) recognize that the class will be generated with the Parcelable interface implemented. I now have two questions:

  • Where does Parceler put the generated classes so that I could work with these? On parceler.org it is stated: "To use the generated code, you may reference the generated class directly, or via the Parcels utility class"
  • Is there another way to use Parceler or any library which generates the Parcelable boilerplate code with Android Annotations?

Until now my code for the Fragment looks like:

@EFragment(R.layout.fragment_faq)
public class FaqFragment extends ListFragment {
    @FragmentArg
    ArrayList<FaqItemImpl> faqItems;
    // ...
}

The generated POJO class is annotated with @Parcel:

@Parcel
public class FaqItemImpl implements FaqItem {
    protected String iconURL;
    protected String title;
    protected String question;
    protected String answer;

    protected ArrayList<FaqItemImpl> faqChildren;
    // ...
}

In the generated FaqFragment_ the interesting part is:

// ...
public FaqFragment_.FragmentBuilder_ faqItems(ArrayList<FaqItemImpl> faqItems) {
        args.putSerializable(FAQ_ITEMS_ARG, faqItems);
        return this;
}
// ...

As you can see the generated class treads the POJO as Serializable...


Solution

  • One approach you can use is to let AA handle the hand-off of the Parcelable and let Parceler perform the serialization/deserialization. One nice feature about Parceler is it will handle collection serialization for you, so AA should just have to deal with a single Parcelable. This would effectively avoid any reference to generated code, besides AA's underscore class of course.

    Here's what I mean:

    @EFragment(R.layout.fragment_faq)
    public class FaqFragment extends ListFragment {
        @FragmentArg
        Parcelable faqParcelable;
    
        public void useFaq(){
            List<FaqItemImpl> faqItems = Parcels.unwrap(faqParcelable);
            // ...
        }
    }
    

    Then when you're ready to build FaqFragment, you would just have to have Parceler wrap your List:

    FaqFragment_.builder()
      .faqParcelable(Parcels.wrap(faqItems))
      .build();
    

    Yes, this approach is not as nice as AA making the wrap/unwrap call for you, but it should work.

    Edit:

    Working with the Android Annotation team we've added Parceler support to @Extra, @FragmentArg and @SavedInstanceState annotated fields. This means the OP's desired functionality is in place. This should work:

    @EFragment(R.layout.fragment_faq)
    public class FaqFragment extends ListFragment {
        @FragmentArg
        ArrayList<FaqItemImpl> faqItems;
        // ...
    }