2017-11-06 11 views
15

Oto moja Retrofit instancja:Jak działa polimorfizmu z Gson (modernizowanych)

@Provides 
@Singleton 
ApiManager provideApiManager() { 
    RxJava2CallAdapterFactory rxAdapter = RxJava2CallAdapterFactory.create(); 

    OkHttpClient okHttpClient = new OkHttpClient.Builder() 
      .addNetworkInterceptor(new StethoInterceptor()) 
      .build(); 

    Gson gson = new GsonBuilder().create(); 
    GsonConverterFactory converterFactory = GsonConverterFactory.create(gson); 

    Retrofit retrofit = new Retrofit.Builder() 
      .baseUrl(AppConstants.BASE_URL) 
      .addConverterFactory(converterFactory) 
      .addCallAdapterFactory(rxAdapter) 
      .client(okHttpClient) 
      .build(); 
    return retrofit.create(ApiManager.class); 
} 

Model:

class AbstractMessage { 
    String id; 
} 

class TextMessage extends AbstractMessage { 
    String textMessage; 
} 

class ImageMessage extends AbstractMessage { 
    String url; 
    String text; 
} 

Zapytanie:

@GET("direct/messages") 
Observable<List<AbstractMessage>> getMessages(@Header("Authorization") String authHeader, @Body RequestObject request); 

Wykonywanie prośba:

apiManager.getMessages(authHeader, requestObject) 
    .subscribeOn(Schedulers.io()) 
    .observeOn(AndroidSchedulers.mainThread()) 
    .subscribe(new Consumer<List<AbstractMessage>>() { 
     @Override 
     public void accept(List<AbstractMessage> messages) throws Exception { 
      ... 
     } 
    }); 

Kiedy wykonuję żądanie, otrzymuję kolekcję obiektów AbstractMessage. JSON może zawierać zarówno wiadomości tekstowe, jak i graficzne. W moim przypadku konwerter JSON tworzy AbstractMessage i odwzorowuje tylko pole id. Jak utworzyć konwerter, aby utworzyć obiekty TextMessage i ImageMessage mapować wszystkie pasujące pola, a następnie przesłać go do AbstractMessage. Lub może istnieć inne rozwiązanie.

+2

Nie wiem, Gson, ale jeśli używasz JacksonConverterFactory zamiast tego, możesz użyć '@ JsonTypeInfo' do utworzenia, w oparciu o pole dyskryminatora, jednego typu lub innego. To jest dobry samouczek: http://www.baeldung.com/jackson-inheritance –

Odpowiedz

17

Należy utworzyć obiekt RuntimeTypeAdapterFactory dla obiektów AbstractMessage, TextMessage i ImageMessage, a następnie ustawić go w instancji Gson.

Załóżmy, że masz te obiekty:

public class Animal { 
    protected String name; 
    protected String type; 

    public Animal(String name, String type) { 
     this.name = name; 
     this.type = type; 
    } 
} 

public class Dog extends Animal { 
    private boolean playsCatch; 

    public Dog(String name, boolean playsCatch) { 
     super(name, "dog"); 
     this.playsCatch = playsCatch; 
    } 
} 

public class Cat extends Animal { 
    private boolean chasesLaser; 

    public Cat(String name, boolean chasesLaser) { 
     super(name, "cat"); 
     this.chasesLaser = chasesLaser; 
    } 
} 

Ten Poniżej RuntimeTypeAdapter które trzeba w celu deserializowania (i serializacji) Właściwe te obiekty:

RuntimeTypeAdapterFactory<Animal> runtimeTypeAdapterFactory = RuntimeTypeAdapterFactory 
    .of(Animal.class, "type") 
    .registerSubtype(Dog.class, "dog") 
    .registerSubtype(Cat.class, "cat"); 

Gson gson = new GsonBuilder() 
    .registerTypeAdapterFactory(runtimeTypeAdapterFactory) 
    .create(); 

Klasa RuntimeTypeAdapterFactory.java nie jest dostarczany z pakietem Gson, więc musisz pobrać i dodać go ręcznie do swojego projektu.

można przeczytać więcej na temat adaptera wykonawczego here i here

Należy pamiętać, że tytuł pytanie powinno być „Polimorfizm z Gson”

Mam nadzieję, że to pomaga.

Powiązane problemy