8

我正在调查auto-value及其扩展,即auto-value-parcelauto-value-parcel-adapter我的 Android 应用程序中。

我有这些模型类:-

@AutoValue
public abstract class Xenarchaeota implements Parcelable {

    @ParcelAdapter(AmoebaTypeAdapter.class)
    public abstract Set<Amoeba> amoebas();

    public static Builder builder() {
        return new AutoValue_Xenarchaeota.Builder();
    }

    @AutoValue.Builder
    public abstract static class Builder {

        public abstract Builder setAmoebas(Set<Amoeba> value);

        public abstract Xenarchaeota build();
    }
}

@AutoValue
public abstract class Amoeba implements Parcelable {

    public abstract String surname();

    public static Builder builder() {
        return new AutoValue_Amoeba.Builder();
    }

    @AutoValue.Builder
    public abstract static class Builder {

        public abstract Builder surname(final String value);

        public abstract Amoeba build();
    }

}

我的类型适配器是我出现问题的地方

class AmoebaTypeAdapter implements TypeAdapter<Set<Amoeba>> {

    @Override
    public Set<Amoeba> fromParcel(Parcel in) {
        final ArrayList<Amoeba> arrayList = new ArrayList<>();
        in.readTypedList(arrayList, Amoeba.CREATOR); // How to access the CREATOR?
        return new TreeSet<>(arrayList);
    }

    @Override
    public void toParcel(Set<Amoeba> value, Parcel dest) {
        final ArrayList<Amoeba> arrayList = new ArrayList<>(value);
        dest.writeTypedList(arrayList);
    }
}

我需要传递给 readTypedArray 的 CREATOR 在 AutoValue_Amoeba 中声明。

我的错误在哪里?误解auto-value-parcel

4

2 回答 2

3

AutoValue:Parcel 扩展无法处理集合,但如果您将属性转换为List事物,则无需自定义适配器即可开箱即用。如果你想把它当作一个Set你可以这样做。请记住,您可能还想缓存Set.

@AutoValue
public abstract class Xenarchaeota implements Parcelable {

    abstract List<Amoeba> amoebaList();
    public Set<Amoeba> amoebas() {
        return new TreeSet(amoebaList());
    }

    public static Builder builder() {
        return new AutoValue_Xenarchaeota.Builder();
    }

    @AutoValue.Builder
    public abstract static class Builder {

        public abstract Builder setAmoebas(Set<Amoeba> value);

        public abstract Xenarchaeota build();
    }
}
于 2018-01-27T20:13:01.723 回答
2

我相信我已经确定了如下解决方案:-

目前auto-value-parcel班级

com.ryanharter.auto.value.parcel.AutoValueParcelExtension

有一个方法叫做generateCreator:-

FieldSpec generateCreator(ProcessingEnvironment env, TypeName autoValueType, List<Property> properties, TypeName type, Map<TypeMirror, FieldSpec> typeAdapters) {
        ClassName creator = ClassName.bestGuess("android.os.Parcelable.Creator");

        TypeName creatorOfClass = ParameterizedTypeName.get(creator, type);
        ...
        ...

此方法生成Parcelable CREATOR类似于此的

public static final Parcelable.Creator<AutoValue_Amoeba> CREATOR = new Parcelable.Creator<AutoValue_Amoeba>() {
    @Override
    public AutoValue_Amoeba createFromParcel(Parcel in) {
      return new AutoValue_Amoeba(
          in.readString()
      );
    }
    @Override
    public AutoValue_Amoeba[] newArray(int size) {
      return new AutoValue_Amoeba[size];
    }
  };

如果 generateCreator 方法更改如下:-

FieldSpec generateCreator(ProcessingEnvironment env, TypeName autoValueType, List<Property> properties, TypeName type, Map<TypeMirror, FieldSpec> typeAdapters) {
        ClassName creator = ClassName.bestGuess("android.os.Parcelable.Creator");

        TypeName creatorOfClass = ParameterizedTypeName.get(creator, autoValueType);  // CHANGE MADE HERE!!! swap type with autoValueType
        ...
        ...

然后,此方法将生成Parcelable CREATOR类似于此的

public static final Parcelable.Creator<Amoeba> CREATOR = new Parcelable.Creator<Amoeba>() {
    @Override
    public AutoValue_Amoeba createFromParcel(Parcel in) {
      return new AutoValue_Amoeba(
          in.readString()
      );
    }
    @Override
    public AutoValue_Amoeba[] newArray(int size) {
      return new AutoValue_Amoeba[size];
    }
  };

这个 CREATOR 现在允许 TypeAdapter 使用 CREATOR,如下所示

class AmoebaTypeAdapter implements TypeAdapter<Set<Amoeba>> {

    @Override
    public Set<Amoeba> fromParcel(Parcel in) {
        final List<Amoeba> arrayList = new ArrayList<>();
        in.readTypedList(arrayList, AutoValue_Amoeba.CREATOR);
        return new TreeSet<>(arrayList);
    }

    @Override
    public void toParcel(Set<Amoeba> value, Parcel dest) {
        final ArrayList<Amoeba> arrayList = new ArrayList<>(value);
        dest.writeTypedList(arrayList);
    }
}
于 2018-01-22T11:50:00.570 回答