Search code examples
androidretrofitrx-java2

Retrofit 2 returns null in production


I'm trying to fix an issue where Retrofit 2 returns null in response. The interesting thing is that in emulator everything works fine, data is received and displayed, but when I build the APK, the same thing crashes with the NullPointerException. I've commented the line where this happens.

My build.gradle dependencies:

compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'io.reactivex.rxjava2:rxjava:2.1.3'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'

Initialize Retrofit:

retrofit = new Retrofit.Builder()
        .baseUrl(<url>)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .build();

Interface:

@GET(<url>)
Flowable<DataResponse> getDataFromApi(@Query("offset") int offset, @Query("limit") int limit);

API call:

retrofit
  .getDataFromApi(0, 10)
  .subscribeOn(Schedulers.io())
  .observeOn(AndroidSchedulers.mainThread())
  .subscribe(new Subscriber<DataResponse>() {
        @Override
        public void onSubscribe(Subscription s) {
            s.request(Long.MAX_VALUE);
        }

        @Override
        public void onNext(DataResponse dataResponse) {
          // HERE I GET NULL IN PRODUCTION   
        }

DataResponse POJO:

public class ServicesResponse {
  private List<Item> items;

  public List<Item> getItems() {
    return items;
  }
}

ProGuard. I've tried several things, but still no luck. It currently looks like this:

-dontwarn retrofit2.**
-keep class javax.annotation.Nullable
-keep interface javax.annotation.Nullable
-keep class retrofit2.** { *; }
-keep class com.squareup.okhttp3.** { *; }
-keep interface com.squareup.okhttp3.** { *; }
-keepattributes Signature
-keepattributes Exceptions
-keepclasseswithmembers class * {
  @retrofit2.http.* <methods>;
}
-keepclasseswithmembers interface * {
  @retrofit2.http.* <methods>;
}

Thanks for the help :)


Solution

  • I always keep model classes used by Retrofit from obfuscation. Otherwise AFAIK Gson can't serialize/deserialize Model:

    -keep public class your.package.to.models.** {*;} 
    
    # or
    
    #-keepclassmembers class your.package.to.models.** {
    #    public <methods>;
    #    <fields>;
    #}