3

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...

John Ericksen
  • 10,995
  • 4
  • 45
  • 75
luckyhandler
  • 10,651
  • 3
  • 47
  • 64

2 Answers2

3

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;
    // ...
}
John Ericksen
  • 10,995
  • 4
  • 45
  • 75
  • Thanks for the answer. It's working this way. When trying this with an activity I get an Exception, though: org.parceler.ParcelerRuntimeException: Unable to create ParcelableFactory for FaqItemImpl. – luckyhandler Apr 17 '15 at 14:38
  • Sounds like Parceler didn't generate the necessary Parcelable. Check that Parceler is configured correctly and that it is generating code. – John Ericksen Apr 17 '15 at 15:04
  • The problem is solved and was not related to this issue. Thanks again. – luckyhandler Apr 20 '15 at 08:51
  • @johncarl nice, i was not aware that `Parcels` has the ability to wrap `List` into one `Parcelable`. – WonderCsabo Apr 20 '15 at 17:49
  • 1
    Thanks @WonderCsabo. This reminds me, I need to add this to the documentation. – John Ericksen Apr 24 '15 at 21:45
  • @JohnEricksen Hi! 1st of all, thx for an amazing lib! I'm experiencing issue here after I've migrated to the gradle 3.0, target and compileSdkVersion 26. I'm using AA 4.4.0 and Parceler 1.1.9. The ArrayList field annotated with Extra is injected with the null value. Could you check it please? – kot331107 Nov 18 '17 at 10:03
  • @kot331107, could you post an issue on github with a full example? – John Ericksen Nov 20 '17 at 20:16
  • @JohnEricksen sure. Here you go https://github.com/androidannotations/androidannotations/issues/2086 :) Actually I'm not sure it's an issue. Maybe a wrong usage. – kot331107 Nov 23 '17 at 07:04
0

Unfortunetaly you cannot use @Parcelable objects with @FragmentArg (or other AA bundle injection annotations). Since you are using FaqItemImpl which itself does not implement Parcelable, AA cannot know how to deal with it. An (ugly) solution would be using the generated class:

@FragmentArg
ArrayList<FaqItemImpl.Parcelable> faqItems;

Actually there was an attempt to integrate parceler into AndroidAnnotations but was rejected due to some reasons.

There are plans to add Parcelable boilerplate generator into AA directly, unfortunetaly it needs more initial work.

WonderCsabo
  • 11,947
  • 13
  • 63
  • 105