Используйте Android аннотации с Parceler


Я использую аннотации Android в своем проекте Android. Поскольку реализация Parcelable - это большая работа, я хочу использовать Parceler и аннотацию @Parcel.

Проблема заключается в том, что если я хочу использовать аннотацию @FragmentArg в аннотациях Android, то она (по понятным причинам) не распознает, что класс будет создан с помощью реализованного интерфейса Parcelable. Теперь у меня есть два вопроса:

  • куда Parceler помещает сгенерированные классы, чтобы я мог работать с ними? На parceler.org сказано: "чтобы использовать сгенерированный код, вы можете ссылаться на сгенерированный класс напрямую или через служебный класс Parcels"
  • есть ли другой способ использовать Parceler или любую библиотеку, которая генерирует Parcelable шаблонный код с аннотациями Android?

До сих пор мой код для фрагмента выглядит так:

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

Сгенерированный класс POJO аннотируется символом @Parcel:

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

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

В сгенерированном Факфрагменте интересна часть это:

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

Как вы можете видеть, сгенерированный класс протекает POJO как сериализуемый...

2 3

2 ответа:

Один из подходов, который вы можете использовать, состоит в том, чтобы позволить AA обрабатывать передачу Parcelable и позволить Parceler выполнять сериализацию/десериализацию. Одна хорошая особенность Parceler - это то, что он будет обрабатывать сериализацию коллекции для вас, поэтому AA должен просто иметь дело с одним Parcelable. Это позволит эффективно избежать любой ссылки на сгенерированный код, кроме класса подчеркивания AA, конечно.

Вот что я имею в виду:

@EFragment(R.layout.fragment_faq)
public class FaqFragment extends ListFragment {
    @FragmentArg
    Parcelable faqParcelable;

    public void useFaq(){
        List<FaqItemImpl> faqItems = Parcels.unwrap(faqParcelable);
        // ...
    }
}

Затем, когда вы будете готовы построить Факфрагмент, вы просто должен иметь Parceler обернуть ваш список:

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

Да, этот подход не так хорош, как AA, делающий вызов wrap/unwrap для вас, но он должен работать.

Edit:

Работая с командой аннотаций Android, мы добавили поддержку Parceler @Extra, @FragmentArg и @SavedInstanceState аннотированные поля. Это означает, что желаемая функциональность OP на месте. Это должно сработать:

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

К сожалению, вы не можете использовать объекты @Parcelable с @FragmentArg (или другими аннотациями инъекции пакета AA). Поскольку вы используете FaqItemImpl , который сам по себе не реализует Parcelable, АА не может знать, как с ним обращаться. (Уродливым) решением было бы использование сгенерированного класса:

@FragmentArg
ArrayList<FaqItemImpl.Parcelable> faqItems;

На самом деле былапопытка интегрировать parceler в AndroidAnnotations, но была отклонена по некоторым причинам.

Есть планы добавить Parcelable шаблонный генератор в АА напрямую, к сожалению это нуждается в дополнительной первоначальной работе.