0

我有这个看起来像这样的基本抽象类。

public abstract class Species implements Parcelable {
    public Species() { 

    }

    public abstract String name();
}

然后我的人类班看起来像这样。

@AutoValue
public abstract class Human extends Species implements Parcelable {
    public static Human create(String humanVariable) {
        return new AutoValue_Human(humanVariable);
    }

    public static Human create(String name, String humanVariable) {
        return new AutoValue_Human(name, humanVariable);
    }

    public static TypeAdapter<Human> typeAdapter(Gson gson) {
        return new AutoValue_Human.GsonTypeAdapter(gson);
    }

    @SerializedName("name")
    public abstract String name();

    @Nullable
    @SerializedName("human_variable")
    public abstract String humanVariable();

}

E/com.service.androidbrain.util.networking.RetrofitCallback.onFailure:无法调用没有参数的公共 com.service.example.models.Species()

但是由于某种原因,我收到了这个错误,我不明白发生了什么,知道吗?

4

4 回答 4

2

auto-value-gson不支持您尝试实现的行为。

我假设你声明你的改造服务返回Call<Species>,而只Human.typeAdapter(Gson)注册到 Gson。这在 Gson 不知道如何实际创建Species.

要完成这项工作,您必须(创建和)安装另一个类型适配器,Species该适配器知道如何识别物种的实际子类型并将所有模型创建委托给特定类型适配器。

于 2017-04-08T18:16:36.267 回答
2

我确定您只是没有GsonConverterFactory正确实例化。从对你上一个问题的回答:

@GsonTypeAdapterFactory
abstract class HumanAdapterFactory
        implements TypeAdapterFactory {

    public static TypeAdapterFactory create() {
        return new AutoValueGson_HumanAdapterFactory();
    }

}

因此,以下是不必要的:

public static TypeAdapter<Human> typeAdapter(Gson gson) {
    return new AutoValue_Human.GsonTypeAdapter(gson);
}

所以你只需要实例化Gson

new GsonBuilder()
        ...
        .registerTypeAdapterFactory(HumanAdapterFactory.create())
        .create();

这样配置改造实例:

new Retrofit.Builder()
        ...
        .addConverterFactory(GsonConverterFactory.create(gson)) // THIS is necessary
        .build();

确保您的服务接口在 上运行Human而不是 Species

interface IService {

    @GET("/") // This is probably what you really want
    Call<Human> getHuman();

    @GET("/") // How can you know WHAT the Species is here?
    Call<Species> getSpecies();

}

如果您真的想使用getSpecies(),您必须知道特定对象的接口的真实类型是什么:因此您必须使用或检测某些信息的真实类型。我的回答中描述了这两种方法。为了使它工作:SpeciesInstanceCreator

final Gson gson = new GsonBuilder()
        .registerTypeAdapterFactory(HumanAdapterFactory.create())
        .registerTypeAdapterFactory(new TypeAdapterFactory() {
            @Override
            public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
                // ... that big type adapter here from that answer OR InstanceCreator by it's not useful here
            }
        })
        .create();

final Retrofit retrofit = new Retrofit.Builder()
        ...
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build();

final IService service = retrofit.create(IService.class);
final Species species = service.getSpecies()
        .execute()
        .body();
System.out.println(species.getClass());
System.out.println(species.name());

这就是您所需要的,但这Call<Human> getHuman();是这里的最佳选择。

于 2017-04-09T15:24:05.443 回答
0

您应该更喜欢组合而不是继承,因为至少目前在AutoValue.

在 github 上查看这个问题。

于 2017-04-08T14:16:22.417 回答
-1

我通过从课堂上删除抽象这个词解决了这个问题

Ej之前

    public abstract class Post {
    
    private int userId;
    private int id;
    private String title;
}

public class Post {
    
    private int userId;
    private int id;
    private String title;
} 
于 2020-07-07T21:42:43.410 回答