androidrx-java2retrofit2.6

Could not locate call adapter for retrofit2.Response<io.reactivex.Single


Android Studio 4.0

build.gradle:

implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'
    implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
    implementation "com.squareup.retrofit2:retrofit:2.6.0"
   implementation 'io.reactivex.rxjava2:rxjava:2.2.10'
    implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'

Config Retrofit:

import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory

  private val builder = Retrofit.Builder()
        .baseUrl(BuildConfig.API_BASE_URL)
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .addConverterFactory(GsonConverterFactory.create(gson))
        .client(httpClient.build())

My interface

import com.myproject.androidtestproject.api.model.Film
import io.reactivex.Single
import retrofit2.Response
import retrofit2.http.GET

interface TestRxJavaRestClient {

    @GET("films")
    fun getFilms(): Response<Single<List<Film>>>

}


import io.reactivex.Single
import retrofit2.Response

class TransportServiceRxJava {
    companion object {
        private val testRxJavaRestClient = RestClientFactory.createRestClient(TestRxJavaRestClient::class.java)


        fun getFilms() : Response<Single<List<Film>>> {
            return testRxJavaRestClient.getFilms()
        }
    }
}

In my ViewModel:

import io.reactivex.Single

class FilmsRxJavaViewModel(application: Application) : AndroidViewModel(application) {
    companion object {
        private val TAG = FilmsRxJavaViewModel::class.java.name
    }

    lateinit var filmsList: Single<List<Film>>

    init {
        Debug.d(TAG, "init:")
        //isShowProgress.value = true
        loadData()
    }

    fun loadData() {
        Debug.d(TAG, "loadData:")
        val response = TransportServiceRxJava.getFilms()
        val isSuccessResponse = response.isSuccessful
        if (isSuccessResponse) { // code >= 200 && code < 300;
            filmsList = response.body()!!
        } else { // error - status (300-599) or network failure
            Debug.w(TAG, "loadData_error: status (300-599) or network_failure")
            val message = response.errorResponse.message
            Debug.w(TAG, "loadData: message = $message")
        }
    }

}

But I get runtime error:

 Process: com.myproject.androidtestproject.debug, PID: 6574
 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.myproject.androidtestproject.debug/com.myproject.androidtestproject.ui.activity.FilmsRxJavaActivity}: java.lang.RuntimeException: Cannot create an instance of class com.myproject.androidtestproject.viewmodel.FilmsRxJavaViewModel
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
 Caused by: java.lang.RuntimeException: Cannot create an instance of class com.myproject.androidtestproject.viewmodel.FilmsRxJavaViewModel
    at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:275)
    at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:106)
    at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:185)
    at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
    at com.myproject.androidtestproject.ui.activity.FilmsRxJavaActivity.init(FilmsRxJavaActivity.kt:57)
    at com.myproject.androidtestproject.ui.activity.FilmsRxJavaActivity.onCreate(FilmsRxJavaActivity.kt:46)
    at android.app.Activity.performCreate(Activity.java:7802)
    at android.app.Activity.performCreate(Activity.java:7791)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
    ... 11 more
 Caused by: java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Constructor.newInstance0(Native Method)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
    at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:267)
    ... 20 more
 Caused by: java.lang.IllegalArgumentException: Unable to create call adapter for retrofit2.Response<io.reactivex.Single<java.util.List<com.myproject.androidtestproject.api.model.Film>>>
     for method TestRxJavaRestClient.getFilms
    at retrofit2.Utils.methodError(Utils.java:52)
    at retrofit2.HttpServiceMethod.createCallAdapter(HttpServiceMethod.java:105)
    at retrofit2.HttpServiceMethod.parseAnnotations(HttpServiceMethod.java:66)
    at retrofit2.ServiceMethod.parseAnnotations(ServiceMethod.java:37)
    at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:170)
    at retrofit2.Retrofit$1.invoke(Retrofit.java:149)
    at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
    at $Proxy0.getFilms(Unknown Source)
    at com.myproject.androidtestproject.service.transport.TransportServiceRxJava$Companion.getFilms(TransportServiceRxJava.kt:21)
    at com.myproject.androidtestproject.viewmodel.FilmsRxJavaViewModel.loadData(FilmsRxJavaViewModel.kt:26)
    at com.myproject.androidtestproject.viewmodel.FilmsRxJavaViewModel.<init>(FilmsRxJavaViewModel.kt:21)
    ... 23 more
 Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for retrofit2.Response<io.reactivex.Single<java.util.List<com.myproject.androidtestproject.api.model.Film>>>.
   Tried:
    * retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
    * retrofit2.CompletableFutureCallAdapterFactory
    * retrofit2.DefaultCallAdapterFactory
    at retrofit2.Retrofit.nextCallAdapter(Retrofit.java:241)
    at retrofit2.Retrofit.callAdapter(Retrofit.java:205)
    at retrofit2.HttpServiceMethod.createCallAdapter(HttpServiceMethod.java:103)
    ... 32 more

Solution

  • You are incorrectly wrapping return type of function getFilms() in TestRxJavaRestClient. Instead of this:

    @GET("films")
    fun getFilms(): Response<Single<List<Film>>>
    

    You should get Response wrapped in Single:

    @GET("films")
    fun getFilms(): Single<Response<List<Film>>>
    

    I would also recommend you to use retrofit2.adapter.rxjava2.Result<T> and not Response<T> for easy connection error handling.