'When using Retrofit I get the error Cannot call adapter
I want to pull crypto data with the retrofit library using the view model and live data functions, but I am getting the following error, I would be very grateful if you could help.
The part that builds the retrofit structure :
object RetrofitInstance {
private val retrofit by lazy {
Retrofit.Builder()
.baseUrl ( BASE_URL )
.addConverterFactory ( GsonConverterFactory.create() )
.build()
}
val api: ApiTerminal by lazy {
retrofit.create ( ApiTerminal::class.java )
}
}
Interface part in this project :
interface ApiTerminal {
@GET("currencies/ticker")
suspend fun getPost ( @Query("key") key : String ): Response<ArrayList<CoinModel>>
}
The repository part in this project :
class Repository {
suspend fun getPost( key : String ) : Response<ArrayList<CoinModel>> {
return RetrofitInstance.api.getPost ( key )
}
}
The part in the project where the view model function is determined :
class MainViewModel ( private val repository: Repository ) : ViewModel() {
val response = MutableLiveData<Response<ArrayList<CoinModel>>>()
fun getPost ( key : String ) {
viewModelScope.launch {
response.value = repository.getPost ( key )
}
}
}
This part of the project is the activity area :
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val viewModelFactory = MainViewModelFactory ( Repository() )
val txt = findViewById<TextView>(R.id.txt)
txt.setOnClickListener {
val viewModel = ViewModelProvider(this, viewModelFactory )[MainViewModel::class.java]
viewModel.getPost("this part contains api key")
viewModel.response.observe(this, Observer {
if (it.isSuccessful) {
txt.text = it.body()?.get(0)?.currency
}
})
}
}
}
The error I got :
2022-04-24 22:01:28.638 5834-5834/com.rk.quex E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.rk.quex, PID: 5834
java.lang.IllegalArgumentException: Unable to create call adapter for class java.lang.Object
for method ApiTerminal.getPost
at retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:752)
at retrofit2.ServiceMethod$Builder.createCallAdapter(ServiceMethod.java:237)
at retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:162)
at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:170)
at retrofit2.Retrofit$1.invoke(Retrofit.java:147)
at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
at $Proxy1.getPost(Unknown Source)
at com.rk.quex.repository.Repository.getPost(Repository.kt:11)
at com.rk.quex.MainViewModel$getPost$1.invokeSuspend(MainViewModel.kt:19)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:367)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25)
at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110)
at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
at kotlinx.coroutines.BuildersKt.launch(Unknown Source:1)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source:1)
at com.rk.quex.MainViewModel.getPost(MainViewModel.kt:17)
at com.rk.quex.MainActivity.onCreate$lambda-1(MainActivity.kt:24)
at com.rk.quex.MainActivity.$r8$lambda$hFYFqoAo62q-drAqh-AGqF7aib8(Unknown Source:0)
at com.rk.quex.MainActivity$$ExternalSyntheticLambda0.onClick(Unknown Source:6)
at android.view.View.performClick(View.java:7448)
at android.view.View.performClickInternal(View.java:7425)
at android.view.View.access$3600(View.java:810)
at android.view.View$PerformClick.run(View.java:28305)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for class java.lang.Object.
Tried:
* retrofit2.ExecutorCallAdapterFactory
at retrofit2.Retrofit.nextCallAdapter(Retrofit.java:241)
at retrofit2.Retrofit.callAdapter(Retrofit.java:205)
at retrofit2.ServiceMethod$Builder.createCallAdapter(ServiceMethod.java:235)
... 32 more
Solution 1:[1]
Can you please try the following:
Please share which Retrofit version dependencies you are using.
Launch the getPost Coroutine in the IO thread:
viewModelScope.launch(Dispatchers.IO) { //code }
Please try to parse the body in the Repository, to get closer to MVVM principles, the ideal would be to create an event response sealed class, to be able to animate the UI depending on the Response, but I won't confuse you and I will make 2 examples, one without the event response and one with:
class Repository {
suspend fun getPost( key : String ) : ArrayList<CoinModel>? {
val response = RetrofitInstance.api.getPost(key)
return if(response.isSuccessful){
response.body?.let { arrayList ->
arrayList
} ?: run {
null
}
} else {
null
}
}
}
Example with event response sealed class:
sealed class Result <out T> {
data class Error <T> (val message: Exception?): Result<T>()
data class Success <T> (val data: T): Result<T>()
}
class Repository {
suspend fun getPost(key: String): Result<List<CoinModel>> {
return try {
val response = RetrofitInstance.api.getPost(key)
if (response.isSuccessful){
response.body()?.let { coinModelList ->
return@let Result.Success(coinModelList)
} ?: run {
Result.Error(Exception("The body is empty"))
}
} else {
Result.Error(Exception("Response not successful"))
}
} catch (e: Exception) {
Result.Error(Exception("Network error"))
}
}
}
This is how it would be from your viewModel:
class MainViewModel ( private val repository: Repository ) : ViewModel() {
val response = MutableLiveData<List<CoinModel>>()
fun getPost ( key : String ) {
viewModelScope.launch(Dispatchers.IO) {
when(val result = repository.getPost ( key )){
is Result.Error -> //Handle your error logic. You can access the Exception message with result.message
is Result.Success -> response.postValue(result.data)
}
}
}
}
Please keep in mind I wrote it "on-hand". I hope it helps :D
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | MACROSystems |
