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
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.