0

I tried to receive list items via Parceler compile 'org.parceler:parceler-api:1.1.5' my code looks like:

 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);
        }
    }

classes:

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);}
}

Compile error is:

...\app\build\generated\source\apt\debug\com\test\objs\NavItem$$Parcelable.java
Error:(63, 26) error: NavItem is abstract; cannot be instantiated
NickUnuchek
  • 11,794
  • 12
  • 98
  • 138
  • 1
    Are you sure that `Parceler` can use abstract classes? Or sure that abstract classes can even be parceled? They need to be instantiated in order to be parceled, right? – OneCricketeer Oct 03 '16 at 08:10
  • @cricket_007 I posted the question to ask maybe anybody know about it – NickUnuchek Oct 03 '16 at 08:12
  • 1
    What happens if you remove the annotation from `NavItem`? – OneCricketeer Oct 03 '16 at 08:13
  • 5
    You don't need to tell me where I can or can't comment. I don't have an answer, so I don't post below. Anyways... The code is auto-generated. `app\build\generated\source\apt\debug\com\test\objs`, which means `Parceler` is trying to verify that it *can*, in fact, parcel your objects. Since you have an abstract class, it cannot pass that test – OneCricketeer Oct 03 '16 at 08:23
  • @cricket_007, I know that `Parceler` tried to create an instance of abstract class in auto-generated files, and question is "How to solve it?" – NickUnuchek Oct 03 '16 at 08:45
  • 2
    And I asked "What happens if you remove the annotation from `NavItem`?" One option if that doesn't work: don't make the class abstract. You are the developer, you should know that you don't need an instance of that class. Or make the constructor protected so you can't create it – OneCricketeer Oct 03 '16 at 08:47
  • 1
    And how about this issue? https://github.com/johncarl81/parceler/issues/237 or this one? https://github.com/johncarl81/parceler/issues/227 – OneCricketeer Oct 03 '16 at 08:50
  • @cricket_007 thanks)). first is very usefull. – NickUnuchek Oct 03 '16 at 08:53

1 Answers1

0

Fixed by adding:

@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;
        }
    }

and added to

@Parcel
public class NavItemsWraper {
    @ParcelPropertyConverter(NavigationItem.NavigationListConverter.class)
    private  List<NavItem> navItems;
NickUnuchek
  • 11,794
  • 12
  • 98
  • 138