我有一个基本的class BaseNewsItem
,以及2个派生类NewsItem
和MovieNewsItem
。然后,有一个MovieListingFeed
类,其中包含一个MovieNewsItem
列表并且是可打包的。它可以在任何活动需要时将此列表打包。
protected MovieNewsListingFeed(Parcel in) {
this.pg = in.readParcelable(PageDetail.class.getClassLoader());
this.items=new ArrayList<>();
in.readTypedList(items, MovieNewsItem.CREATOR);
}
我在此行收到错误消息:
in.readTypedList(items, MovieNewsItem.CREATOR);
错误:
Error:(60, 11) error: method readTypedList in class Parcel cannot be applied to given types; required: List<T>,Creator<T> found: ArrayList<CAP#1>,Creator<CAP#2> reason: inferred type does not conform to equality constraint(s) inferred: CAP#2 equality constraints(s): CAP#2,CAP#1 where T is a type-variable: T extends Object declared in method <T>readTypedList(List<T>,Creator<T>) where CAP#1,CAP#2 are fresh type-variables: CAP#1 extends BaseNewsItem from capture of ? extends BaseNewsItem CAP#2 extends BaseNewsItem from capture of ? extends BaseNewsItem
我是Generics的新手,因此当我搜索上述错误时,并没有完全发布解决方案。我只是添加了将
ArrayList<MovieNewsItem>
转换为ArrayList<BaseNewsItem>
所需的内容。MovieNewsItem类中的相关代码:
public static final Creator<? extends BaseNewsItem> CREATOR = new Creator<MovieNewsItem>() {
public MovieNewsItem createFromParcel(Parcel source) {
return new MovieNewsItem(source);
}
public MovieNewsItem[] newArray(int size) {
return new MovieNewsItem[size];
}
};
让我知道是否需要其他代码片段。
更新1 :(来自Android框架的readTypedList。)
public final <T> void readTypedList(List<T> list, Parcelable.Creator<T> c) {
int M = list.size();
int N = readInt();
int i = 0;
for (; i < M && i < N; i++) {
if (readInt() != 0) {
list.set(i, c.createFromParcel(this));
} else {
list.set(i, null);
}
}
for (; i<N; i++) {
if (readInt() != 0) {
list.add(c.createFromParcel(this));
} else {
list.add(null);
}
}
for (; i<M; i++) {
list.remove(N);
}
}
MovieNewsListingFeed.java(问题文件):
public class MovieNewsListingFeed implements Parcelable {
PageDetail pg;
public void setItems(ArrayList<? extends BaseNewsItem> items) {
this.items = items;
}
ArrayList<? extends BaseNewsItem> items;
public ArrayList<? extends BaseNewsItem> getItemsTemp() {
return itemsTemp;
}
public void setItemsTemp(ArrayList<? extends BaseNewsItem> itemsTemp) {
this.itemsTemp = itemsTemp;
}
ArrayList<? extends BaseNewsItem> itemsTemp;
public ArrayList<? extends BaseNewsItem> getItems() {
return items;
}
public PageDetail getPg() {
return pg;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(this.pg, flags);
dest.writeTypedList(items);
}
public MovieNewsListingFeed() {
}
protected MovieNewsListingFeed(Parcel in) {
this.pg = in.readParcelable(PageDetail.class.getClassLoader());
this.items = new ArrayList<>();
in.readTypedList(items, MovieNewsItem.CREATOR);
}
public static final Parcelable.Creator<MovieNewsListingFeed> CREATOR = new Parcelable.Creator<MovieNewsListingFeed>() {
public MovieNewsListingFeed createFromParcel(Parcel source) {
return new MovieNewsListingFeed(source);
}
public MovieNewsListingFeed[] newArray(int size) {
return new MovieNewsListingFeed[size];
}
};
}
MovieNewsItem.java:
public class MovieNewsItem extends BaseNewsItem implements Parcelable {
String hl;
String imageid;
String syn;
String id;
String dm;
String tn;
String dl = "";
String sectionHeader;
String upd;
String ud;
private int validListPosition = -1;
public int getValidListPosition() {
return validListPosition;
}
@Override
public void setTitle(String title) {
}
@Override
public void setId(String id) {
}
@Override
public void setDate(String date) {
}
@Override
public void setNewsType(int newsType) {
}
public String getFormatedDate() {
return formatedDate;
}
String formatedDate;
int position;
int newSectionType = NewsType.CONTENT_TYPE_NEWS;
String dayHeading;
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
public void setNewSectionType(int newSectionType) {
this.newSectionType = newSectionType;
}
public String getDayHeading() {
return dayHeading;
}
public void setDayHeading(String dayHeading) {
this.dayHeading = dayHeading;
}
@Override
public void setValidListPosition(int listPosition) {
}
public String getWu() {
return wu;
}
String wu;
public String getHl() {
return hl;
}
public String getImageid() {
return imageid;
}
public String getSyn() {
return syn;
}
public String getId() {
return id;
}
public String getDm() {
return dm;
}
public String getTn() {
return tn;
}
public String getDl() {
return dl;
}
public String getSectionHeader() {
return sectionHeader;
}
public MovieNewsItem() {
}
@Override
public String getTitle() {
return (!TextUtils.isEmpty(getSyn())) ? getSyn() : getHl();
}
@Override
public String getDate() {
return getFormatedDate();
}
@Override
public int getNewsType() {
return newSectionType;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.hl);
dest.writeString(this.imageid);
dest.writeString(this.syn);
dest.writeString(this.id);
dest.writeString(this.dm);
dest.writeString(this.tn);
dest.writeString(this.dl);
dest.writeString(this.sectionHeader);
dest.writeString(this.upd);
dest.writeString(this.ud);
dest.writeInt(this.position);
dest.writeInt(this.newSectionType);
dest.writeString(this.dayHeading);
dest.writeString(this.wu);
}
protected MovieNewsItem(Parcel in) {
this.hl = in.readString();
this.imageid = in.readString();
this.syn = in.readString();
this.id = in.readString();
this.dm = in.readString();
this.tn = in.readString();
this.dl = in.readString();
this.sectionHeader = in.readString();
this.upd = in.readString();
this.ud = in.readString();
this.position = in.readInt();
this.newSectionType = in.readInt();
this.dayHeading = in.readString();
this.wu = in.readString();
}
public static final Creator<? extends BaseNewsItem> CREATOR = new Creator<MovieNewsItem>() {
public MovieNewsItem createFromParcel(Parcel source) {
return new MovieNewsItem(source);
}
public MovieNewsItem[] newArray(int size) {
return new MovieNewsItem[size];
}
};
@Override
public boolean equals(Object obj) {
MovieNewsItem newsItem = this;
if (obj instanceof MovieNewsItem) {
MovieNewsItem oldNewsItem = (MovieNewsItem) obj;
if (oldNewsItem != null &&
newsItem.id.equals(oldNewsItem.id)) {
return true;
}
}
return false;
}
}
BaseNewsItem.java:
public abstract class BaseNewsItem implements NewsItemType {
}
NewsItemType.java:
public interface NewsItemType extends Parcelable {
String getTitle();
String getId();
String getDate();
int getNewsType();
String getDayHeading();
int getValidListPosition();
int getPosition();
void setTitle(String title);
void setId(String id);
void setDate(String date);
void setNewsType(int newsType);
void setDayHeading(String dayHeading);
void setValidListPosition(int listPosition);
void setPosition(int position);
}
最佳答案
您的问题可以通过以下最小示例来重现(用? extends Object
替换? extends BaseNewsItem
,用Parcelable.Creator
替换第二个列表,您会发现逻辑完全相同):
public void test() {
List<? extends Object> a1 = new ArrayList<> ();
List<? extends Object> a2 = new ArrayList<> ();
m(a1, a2); //your compilation error here
}
public <T> void m(List<T> a1, List<T> a2) { }
问题在于两个列表的泛型类型是不相关的:它们都扩展了相同的基类,但这就是我们所了解的全部-例如,
a1
可能是List<String>
,而a2
是List<Integer>
。但是,
m
方法期望两个泛型类型相同-这不是您要传递的类型。因此,您需要传递具有相同泛型的列表,例如:
public void test() {
List<SomeBaseClass> a1 = new ArrayList<> ();
List<SomeBaseClass> a2 = new ArrayList<> ();
m(a1, a2); //compiles fine
}
public <T> void m(List<T> a1, List<T> a2) { }