Issue
I'm attempting to use retrofit2 for the first time. I read online many tutorials and read the docs. I understand the steps and didn't expect any errors ;) but when I run the app, I get the following error :
Caused by: java.lang.IllegalArgumentException: Unable to create call adapter for
java.util.List<com.example.myretrofit.MarsPhoto>
for method MarsApiService.getPhotos
I used the create app with noActivity so my code is the basic code but added retrofit on top of the file. I just wanted to try retrofit and initiating a get call to an api.
Here is the code MainActivity.kt using kotlinx.serilization for json and retrofit2 for http get:
package com.example.myretrofit
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.myretrofit.ui.theme.MyRetrofitTheme
//retrofit implementation
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import retrofit2.Retrofit
import retrofit2.http.GET
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import retrofit2.Call
import kotlinx.serialization.encodeToString
/**
* This data class defines a Mars photo which includes an ID, and the image URL.
*/
@Serializable
data class MarsPhoto(
val id: String,
@SerialName(value = "img_src")
val imgSrc: String
)
private const val BASE_URL =
"https://android-kotlin-fun-mars-server.appspot.com"
/**
* Use the Retrofit builder to build a retrofit object using a kotlinx.serialization converter
*/
private val retrofit = Retrofit.Builder()
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
.baseUrl(BASE_URL)
.build()
/**
* Retrofit service object for creating api calls
*/
interface MarsApiService {
@GET("photos")
fun getPhotos(): List<MarsPhoto>
}
/**
* A public Api object that exposes the lazy-initialized Retrofit service
*/
object MarsApi {
val retrofitService: MarsApiService by lazy {
retrofit.create(MarsApiService::class.java)
}
}
//end of retrofit implementation
val listResult = MarsApi.retrofitService.getPhotos()
// for (item in listResult) {
// Log.i("ServerItem : ", "$item")
// }
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyRetrofitTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
val listResult = MarsApi.retrofitService.getPhotos()
Log.i("ServerItem : ", "print something")
Greeting("Android")
}
}
}
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
MyRetrofitTheme {
Greeting("Android")
}
}
Clearly I missed something while reading all the tutorials and docs for retrofit2. The error indicates that the interface code is wrong but I don't know why? I don't have an adapter and I actually don't need an adapter with kotlinx.serilization, right??
How to fix this error so I can get the response from the api?
The docs is here
Please keep in mind that I'm at level 0 in android studio/kotlin/apps development. I just started three weeks ago. I understand and able to use compose well. I understand how to work with activities and coroutines. I don't want to add coRoutines here because I wanted to understand retrofit2 so I'm ok with the call blocking the thread.
I believe the error is because the interface is fun getPhotos() when I take it out, the error goes away, the app runs correctly but I get nothing from the retrofit instance. No logging of any type.
Thank you for trying to help.
How to fix this error so I can get the response from the api?
Solution
kotlinx.serialization
is not officially available as a converter factory for Retrofit. If you still want to use it with Retrofit you need to use this library.
However, I would suggest an easier option like GsonConverter
which is available for Retrofit. To do this, first, add the dependency:
implementation("com.squareup.retrofit2:converter-gson:<your_retrofit_version>")
And then, add the converter factory when creating the Retrofit client:
Retrofit.Builder()
.baseUrl("<your_api_base_url>")
.addConverterFactory(GsonConverterFactory.create())
.build()
For a more detailed usecase in a project with dependency injection check out this.
Answered By - Atick Faisal
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.