将对象转换为 Parcelable 超类的子类?
Posted
技术标签:
【中文标题】将对象转换为 Parcelable 超类的子类?【英文标题】:Casting objects to subclasses of a Parcelable superclass? 【发布时间】:2014-03-09 15:00:22 【问题描述】:好的,所以我有一个课程SomeClass
,即Parcelable
。
它有一个名为SuperClass
的另一个Parcelable
类的数组。在SomeClass
的构造函数中,我试图将SuperClass
对象的数组读入myArray
实例变量。这很简单;但是:
SuperClass
有两个子类FirstSubClass
和SecondSubClass
。数组 temp
应该是所有 3 个的混合,但由于某种原因它只有 SuperClass
对象(if
和 else if
语句似乎没有执行,因为 @987654335 的任何元素都没有@ 是子类的实例)。
public SomeClass(Parcel in)
myArray = new SuperClass[100];
// this is probably where the problem is due to the classloader parameter:
Object[] temp = in.readArray(SuperClass.class.getClassLoader());
for(int i = 0; i < myArray.length; i++)
if(temp[i] instanceof FirstSubClass)
myArray[i] = (FirstSubClass) temp[i];
else if(temp[i] instanceof SecondSubClass)
myArray[i] = (SecondSubClass) temp[i];
else
myArray[i] = (SuperClass) temp[i];
我想弄清楚的是如何读取可打包对象数组的元素,以便该对象的子类不会自动转换为超类。
(我想我的问题措辞可能很混乱,如果我这样做了,请告诉我)。
【问题讨论】:
Parcelable 是接口还是超类?和 SomeClass 在其构造函数中接受的 Parcel 一样吗?Parcelable
是SomeClass
和SuperClass
都实现的接口。 Parcel
是一个类。
包裹怎么写?
【参考方案1】:
我试图重现您的问题,但我无法...我使用了 writeParcelableArray
和 NOT writeTypedArray
。以下是我创建的类:
public class SuperClass implements Parcelable
public static final Parcelable.Creator<SuperClass> CREATOR = new Creator<SuperClass>()
@Override
public SuperClass[] newArray(int size)
return new SuperClass[size];
@Override
public SuperClass createFromParcel(Parcel source)
return new SuperClass(source);
;
private String label;
public SuperClass()
protected SuperClass(Parcel source)
label = source.readString();
@Override
public void writeToParcel(Parcel dest, int flags)
dest.writeString(label);
@Override
public int describeContents()
// TODO Auto-generated method stub
return 0;
及其子类:
public class FirstSubClass extends SuperClass
public static final Parcelable.Creator<FirstSubClass> CREATOR = new Creator<FirstSubClass>()
@Override
public FirstSubClass[] newArray(int size)
return new FirstSubClass[size];
@Override
public FirstSubClass createFromParcel(Parcel source)
return new FirstSubClass(source);
;
public FirstSubClass()
super();
public FirstSubClass(Parcel source)
super(source);
和:
public class SecondSubClass extends SuperClass
public static final Parcelable.Creator<SecondSubClass> CREATOR = new Creator<SecondSubClass>()
@Override
public SecondSubClass[] newArray(int size)
return new SecondSubClass[size];
@Override
public SecondSubClass createFromParcel(Parcel source)
return new SecondSubClass(source);
;
public SecondSubClass()
super();
public SecondSubClass(Parcel source)
super(source);
还有SomeClass
:
public class SomeClass implements Parcelable
public static final Parcelable.Creator<SomeClass> CREATOR = new Creator<SomeClass>()
@Override
public SomeClass[] newArray(int size)
return new SomeClass[size];
@Override
public SomeClass createFromParcel(Parcel source)
return new SomeClass(source);
;
private String name;
private SuperClass[] array;
public SomeClass(String name, SuperClass[] array)
this.name = name;
this.array = array;
protected SomeClass(Parcel source)
this.name = source.readString();
Parcelable[] temp = source.readParcelableArray(SuperClass.class.getClassLoader());
array = new SuperClass[temp.length];
for (int i = 0; i < temp.length; i++)
array[i] = (SuperClass) temp[i];
public String toString()
StringBuilder sb = new StringBuilder(name);
if (array == null || array.length == 0)
sb.append(" Array is empty");
else
sb.append(" Array:");
for (SuperClass sc : array)
sb.append(sc.getClass().getSimpleName());
sb.append(",");
sb.setLength(sb.length() - 1);
return sb.toString();
public String getName()
return name;
public SuperClass[] getArray()
return array;
@Override
public void writeToParcel(Parcel dest, int flags)
dest.writeString(name);
dest.writeParcelableArray(array, flags);
@Override
public int describeContents()
return 0;
从一个活动中,我点击一个按钮,创建一个SomeClass
对象,附加到我启动一个新活动的意图,并从那里记录传递的值。启动活动的函数:
@Override
public void onClick(View v)
SuperClass[] array = new SuperClass[] new SuperClass(), new FirstSubClass(), new SecondSubClass(), new SuperClass() ;
SomeClass cl = new SomeClass("My Label", array);
Intent intent = new Intent(this, NextActivity.class);
intent.putExtra("PASS", cl);
startActivity(intent);
来自NextActivity
:
public class NextActivity extends Activity
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
//set some content if you wish
Log.d("LOG_TAG", "Passed value: " + getIntent().getParcelableExtra("PASS"));
我可以在日志中看到:
Passed value: My Label Array:SuperClass,FirstSubClass,SecondSubClass,SuperClass
正是我从以前的活动中传递的内容...检查与您的代码的差异,我怀疑您没有为FirstSubClass
和SecondSubClass
编写CREATOR
【讨论】:
我在所有 3 个类中都有CREATOR
变量,所以不可能。我将尝试将您的其余代码与我的课程进行比较;如果我仍然找不到问题,我会发布我的代码 - 感谢您的帮助!
我看了你的代码几次才发现问题!问题是我使用的方法是writeTypedArray
而不是writeParcelableArray
,它允许传递具有多种类型对象的数组;您能否更新您的答案以强调这是解决方案,以防万一其他人遇到此问题?
我的超类是一个抽象类..你认为我应该为我的结构做些什么..?
谢谢,很好的解决方案!【参考方案2】:
不确定为什么需要在 readArray 方法中获取类加载器,但我试了一下并为您的代码制作了一个示例 - 所以整个示例有几段代码。
示例 Parcelable 类 - 示例中其他一些类的基类
/**
*/
public class Parcelable
public String parcel()
return "in Parcelable.parcel()...";
示例 SomeClass - 更改为强制数组匹配我从 Parcel 类返回的硬编码大小。如果数组只包含这些类型,那么您可以只转换为 Parcelable 而不必转换为 FirstSubClass、SecondSubClass 和 SuperClass。
/**
*/
public class SomeClass extends Parcelable
private Parcelable[] myArray;
public SomeClass(Parcel in)
myArray = new SuperClass[3];
// this is probably where the problem is due to the classloader parameter:
//Object[] temp = in.readArray(SuperClass.class.getClassLoader());
Object[] temp = in.readArray();
/*
for(int i = 0; i < 3; i++)
if(temp[i] instanceof FirstSubClass)
myArray[i] = (FirstSubClass) temp[i];
else if(temp[i] instanceof SecondSubClass)
myArray[i] = (SecondSubClass) temp[i];
else
myArray[i] = (SuperClass) temp[i];
*/
for(int i = 0; i < 3; i++)
myArray[i] = (Parcelable) temp[i];
public String parcel()
return "In SomeClass.parcel()...";
public void show()
for (Parcelable p : myArray)
System.out.println (p.parcel());
public static void main(String[] args )
SomeClass sc = new SomeClass(new Parcel());
sc.show();
示例包裹类 - 由于没有信息而不得不伪造。
/**
*/
public class Parcel
public Object[] readArray()
Object[] array = new Object[3];
array[0] = new SuperClass();
array[1] = new FirstSubClass();
array[2] = new SecondSubClass();
return array;
示例超类
/**
*/
public class SuperClass extends Parcelable
public String parcel()
return "In SuperClass.parcel()...";
FirtSubClass 示例
/**
*/
public class FirstSubClass extends SuperClass
public String parcel()
return "In FirstSubClass.parcel()...";
示例 SecondSubClass
/**
*/
public class SecondSubClass extends SuperClass
public String parcel()
return "In SecondSubClass.parcel()...";
【讨论】:
以上是关于将对象转换为 Parcelable 超类的子类?的主要内容,如果未能解决你的问题,请参考以下文章