Parceler: как решить проблему: ошибка: элемент является абстрактным; не может быть создан

#java #android #bundle #parcel #parceler

#java #Android #пакет #посылка #parceler

Вопрос:

Я попытался получить элементы списка через Parceler, compile 'org.parceler:parceler-api:1.1.5' мой код выглядит так:

  protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        List<NavItem> navItems = new ArrayList<>();
        navItems.add(new CategoryItem("CategoryItem"));
        navItems.add(new SubCatItem("SubCatItem"));

        NavItemsWraper wraper = new NavItemsWraper(navItems);
        Intent data = new Intent();
        data.putExtra("data", Parcels.wrap(wraper));

        NavItemsWraper recievedWraper = Parcels.unwrap(data.getParcelableExtra("data"));
        recievedWraper.getNavItems();
        for (NavItem item:recievedWraper.getNavItems()){
            Log.e(TAG, "onCreate: " item.title);
        }
    }
  

классы:

NavItem

 @Parcel
public abstract class NavItem {
    public String title;

    public NavItem(){

    }

    public NavItem(String subCatItem) {
        this.title=subCatItem;
    }
}
  

NavItemsWrapper

 @Parcel
public class NavItemsWraper {
    private  List<NavItem> navItems;

    public NavItemsWraper(){

    }

    public NavItemsWraper(List<NavItem> navItems) {

        this.navItems=navItems;
    }

    public List<NavItem> getNavItems() {
        return navItems;
    }
}
  

CategoryItem

 @Parcel
public class CategoryItem extends NavItem {
    public CategoryItem(){

    }
    public CategoryItem(String categoryItem) {
        super(categoryItem);
    }
}
  

SubCategoryItem

 @Parcel
public class SubCatItem extends NavItem {
    public SubCatItem() {
    }

    public SubCatItem(String subCatItem) {super(subCatItem);}
}
  

Ошибка компиляции:

 ...appbuildgeneratedsourceaptdebugcomtestobjsNavItem$$Parcelable.java
Error:(63, 26) error: NavItem is abstract; cannot be instantiated
  

Комментарии:

1. Вы уверены, что Parceler можете использовать абстрактные классы? Или уверен, что абстрактные классы можно даже разделить? Они должны быть созданы для того, чтобы быть обработаны, верно?

2. Что произойдет, если вы удалите аннотацию из NavItem ?

3. Вам не нужно указывать мне, где я могу или не могу комментировать. У меня нет ответа, поэтому я не публикую ниже. В любом случае… Код генерируется автоматически. , что означает попытку проверить, действительно ли он может посылать ваши объекты. appbuildgeneratedsourceaptdebugcomtestobjs Parceler Поскольку у вас есть абстрактный класс, он не может пройти этот тест

4. И я спросил: «Что произойдет, если вы удалите аннотацию из NavItem ?» Один из вариантов, если это не сработает: не делайте класс абстрактным. Вы разработчик, вы должны знать, что вам не нужен экземпляр этого класса. Или сделайте конструктор защищенным, чтобы вы не могли его создать

5. И как насчет этой проблемы? github.com/johncarl81/parceler/issues/237 или этот? github.com/johncarl81/parceler/issues/227

Ответ №1:

Исправлено путем добавления:

 @Parcel(converter = NavigationItem.NavigationItemConverter.class)
public abstract class NavigationItem   {
  

  public static class NavigationItemConverter  implements ParcelConverter<NavigationItem> {

        public static final int KEY_CategoryItem = 1;
        public static final int KEY_SubCatItem = 2;
        @Override
        public void toParcel(NavigationItem input, android.os.Parcel parcel) {
            if (input == null) {
                parcel.writeInt(-1);
            } else {

                if (input instanceof CategoryItem) {
                    parcel.writeInt(KEY_CategoryItem);
                    parcel.writeParcelable(Parcels.wrap((CategoryItem) input), 0);
                }
                if (input instanceof SubCategoryItem) {
                    parcel.writeInt(KEY_SubCatItem);
                    parcel.writeParcelable(Parcels.wrap((SubCategoryItem) input), 0);

                }
            }
        }

        @Override
        public NavigationItem fromParcel(android.os.Parcel parcel) {
            NavigationItem item = null;
            int key = parcel.readInt();
            if (key == KEY_CategoryItem){
                item = Parcels.unwrap(parcel.readParcelable(CategoryItem.class.getClassLoader()));
            }
            if (key == KEY_SubCatItem){
                item = Parcels.unwrap(parcel.readParcelable(SubCategoryItem.class.getClassLoader()));
            }
            return item;
        }
    }

    public static class NavigationListConverter  implements ParcelConverter<List<NavigationItem>> {

        @Override
        public void toParcel(List<NavigationItem> input, android.os.Parcel parcel) {
            if (input == null) {
                parcel.writeInt(-1);
            } else {
                parcel.writeInt(input.size());
                for (NavigationItem item : input) {
                    parcel.writeParcelable(Parcels.wrap(item), 0);
                }
            }
        }

        @Override
        public List<NavigationItem> fromParcel(android.os.Parcel parcel) {
            int size = parcel.readInt();
            if (size < 0) return null;
            List<NavigationItem> items = new ArrayList<NavigationItem>();
            for (int i = 0; i < size;   i) {
                NavigationItem item = Parcels.unwrap(parcel.readParcelable(NavigationItem.class.getClassLoader()));
                items.add(item);
            }
            return items;
        }
    }
  

и добавлен в

 @Parcel
public class NavItemsWraper {
    @ParcelPropertyConverter(NavigationItem.NavigationListConverter.class)
    private  List<NavItem> navItems;