#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;