java - 在侦听器中调用 getValue() 时,android firebase 无法实例化抽象类
问题描述
我有一个装备类,它有一个抽象类作为它的属性之一。当我侦听数据库中的更改时,我收到此错误java.lang.RuntimeException: java.lang.InstantiationException: Can't instantiate abstract class com.example.recouture.Item
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Query query = reference.child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("Outfits");
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot singleSnapshot : dataSnapshot.getChildren()) {
outfits.add(singleSnapshot.getValue(Outfit.class)); //error is here
}
是否有可能绕过这一点,因为使 Item 非抽象会导致我的其他代码部分出现设计问题。Item 是抽象的,因为它可以包含从 Item 类扩展而来的 Shirt、Pants 等。
服装.java
public class Outfit implements Parcelable{
private List<Item> itemList = new ArrayList<>();
private String mName;
private String mImageUrl;
public Outfit() {}
public Outfit(String mName, String mImageUrl,List<Item> items) {
this.mName = mName;
this.mImageUrl = mImageUrl;
this.itemList = items;
}
public List<Item> getItemList() {
return itemList;
}
protected Outfit(Parcel in) {
in.readList(itemList,Item.class.getClassLoader());
mName = in.readString();
mImageUrl = in.readString();
}
public static final Creator<Outfit> CREATOR = new Creator<Outfit>() {
@Override
public Outfit createFromParcel(Parcel in) {
return new Outfit(in);
}
@Override
public Outfit[] newArray(int size) {
return new Outfit[size];
}
};
public String getmName() {
return mName;
}
public String getmImageUrl() {
return mImageUrl;
}
@Override
public String toString() {
return mName;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeList(itemList);
parcel.writeString(mName);
parcel.writeString(mImageUrl);
}
public void setItemList(List<Item> itemList) {
this.itemList = itemList;
}
}
public abstract class Item implements Parcelable {
private String mName;
private String mColor;
private String mImageUrl;
private List<TagHolder> tags = new ArrayList<>();
private String mKey;
public Item(){
}
public Item(String mName, String mColor, String mImageUrl) {
this.mName = mName;
this.mColor = mColor;
this.mImageUrl = mImageUrl;
}
protected Item(Parcel in) {
mName = in.readString();
mColor = in.readString();
mImageUrl = in.readString();
tags = in.createTypedArrayList(TagHolder.CREATOR);
mKey = in.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mName);
dest.writeString(mColor);
dest.writeString(mImageUrl);
dest.writeTypedList(tags);
dest.writeString(mKey);
}
@Override
public int describeContents() {
return 0;
}
public void setmName(String mName) {
this.mName = mName;
}
public void setmImageUrl(String mImageUrl) {
this.mImageUrl = mImageUrl;
}
public List<TagHolder> getTags() {
return tags;
}
public String getmColor() {
return mColor;
}
public String getmImageUrl() {
return mImageUrl;
}
public void setmColor(String mColor) {
this.mColor = mColor;
}
public String getmName() {
return mName;
}
public void setTags(List<TagHolder> tags) {
this.tags = tags;
}
@Exclude // dont need this in our firebase database
public String getKey() {
return mKey;
}
@Exclude
public void setMkey(String key) {
mKey = key;
}
public abstract String getCategory();
}
firebase 数据库结构:
userid : {
outfits : {
uniqueKey1 : {
itemList : {
0: {..}
1: {...}
}
mName : {...}
mImageUrl : {...}
} // uniquekey1
uniqueKey2 : {
itemList : {
0: {..}
1: {...}
}
mName : {...}
mImageUrl : {...}
} // end unique key 2
}
} //end outfits
} // end user id
完整的堆栈跟踪:
08-02 00:04:28.191 6353-6353/com.example.recouture E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.recouture, PID: 6353
java.lang.RuntimeException: java.lang.InstantiationException: Can't instantiate abstract class com.example.recouture.Item
at com.google.android.gms.internal.zzelx.zze(Unknown Source:305)
at com.google.android.gms.internal.zzelw.zzb(Unknown Source:196)
at com.google.android.gms.internal.zzelw.zza(Unknown Source:301)
at com.google.android.gms.internal.zzelw.zza(Unknown Source:60)
at com.google.android.gms.internal.zzelw.zzb(Unknown Source:0)
at com.google.android.gms.internal.zzelx.zze(Unknown Source:125)
at com.google.android.gms.internal.zzelw.zzb(Unknown Source:196)
at com.google.android.gms.internal.zzelw.zza(Unknown Source:0)
at com.google.firebase.database.DataSnapshot.getValue(Unknown Source:10)
at com.example.recouture.Outfit.ViewOutfits$2.onDataChange(ViewOutfits.java:74) // line of my error
at com.google.firebase.database.zzp.onDataChange(Unknown Source:7)
at com.google.android.gms.internal.zzegf.zza(Unknown Source:13)
at com.google.android.gms.internal.zzeia.zzbyc(Unknown Source:2)
at com.google.android.gms.internal.zzeig.run(Unknown Source:71)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.InstantiationException: Can't instantiate abstract class com.example.recouture.Item
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at com.google.android.gms.internal.zzelx.zze(Unknown Source:53)
at com.google.android.gms.internal.zzelw.zzb(Unknown Source:196)
at com.google.android.gms.internal.zzelw.zza(Unknown Source:301)
at com.google.android.gms.internal.zzelw.zza(Unknown Source:60)
at com.google.android.gms.internal.zzelw.zzb(Unknown Source:0)
at com.google.android.gms.internal.zzelx.zze(Unknown Source:125)
at com.google.android.gms.internal.zzelw.zzb(Unknown Source:196)
at com.google.android.gms.internal.zzelw.zza(Unknown Source:0)
at com.google.firebase.database.DataSnapshot.getValue(Unknown Source:10)
at com.example.recouture.Outfit.ViewOutfits$2.onDataChange(ViewOutfits.java:74)
at com.google.firebase.database.zzp.onDataChange(Unknown Source:7)
at com.google.android.gms.internal.zzegf.zza(Unknown Source:13)
at com.google.android.gms.internal.zzeia.zzbyc(Unknown Source:2)
at com.google.android.gms.internal.zzeig.run(Unknown Source:71)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
解决方案
您的具体Outfit
类具有定义的字段和属性Item
:
public class Outfit implements Parcelable{
private List<Item> itemList = new ArrayList<>();
...
public List<Item> getItemList()
这意味着 Firebase SDK 将尝试实例化一个Item
,这是不可能的,因为它是抽象的。您很可能希望 Firebase 在Item
读取数据时实例化正确的(具体)子类型,但它无法知道那是什么子类型。
您要么必须标记Item
为非抽象,要么必须将 标记itemList
为具有特定的具体子类型Item
.
推荐阅读
- jackson - Jackson 解析具有不同类的 XML 文件,这些类都继承自同一个父类
- javascript - 标记和扫描算法是否仅适用于参考?
- selenium - Selenium 无法绕过 NTLM 身份验证对话框
- r - R闪亮的地图标记点击事件
- javascript - 如何在 three.js 上添加 OrbitControls
- javascript - 仅当在 JavaScript 中单击按钮时才激活预加载器
- python - 如何在使用 SQLACHEMY 作为 ORM 的顾问中转换 thi 查询
- javascript - vuejs从js方法DOM创建onclick事件
- android - 在 ViewHolder 中添加 Listener 用于 Fragment 与 Activity 通信
- html - img 没有拉伸到包装器的高度和宽度