my problem is kinda common. After checking tons of resources i still cant find any solutions. In some cases people saying to use List of models, instead of models. But the problem existed with List of models. In this case i work with MVVM pattern. Let me show.
Asnwer which i will get if example word: policeman
{"head":{},"def":[{"text":"lawman","pos":"noun","ts":"lɔːmæn","tr":[{"text":"officer","pos":"noun","fr":1,"syn":[{"text":"policeman","pos":"noun","fr":1}]}]}]}
The API looks like a dictionary, which return similar words when user typing a word
In code im only need to get these similar words and show it.
Model class
data class DictModel(
val text : String
)
Api Object
object DictApiObject {
private val retrofit by lazy {
Retrofit.Builder()
.baseUrl("https://dictionary.yandex.net/api/v1/dicservice.json/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
val api : DictAPI by lazy {
retrofit.create(DictAPI::class.java)
}
}
Api interface
interface DictAPI {
@GET("lookup")
suspend fun getTextFromDictApi(
@Query("key") apiKey : String,
@Query("lang") lang : String,
@Query("text") text : String
): Response<List<DictModel>>
}
Repository method
suspend fun getTextFromApi(apiKey : String, lang : String, text:String) : Response<List<DictModel>> {
return DictApiObject.api.getTextFromDictApi(apiKey, lang, text)
}
ViewModel var, method, factory
var myResponse: MutableLiveData<Response<List<DictModel>>> = MutableLiveData()
fun getTextApi(apiKey : String, lang : String, text:String) {
viewModelScope.launch{
val response = cardRepository.getTextFromApi(apiKey, lang, text)
myResponse.value = response
}
}
class CardViewModelFactory(private val application: Application) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@Suppress("UNCHECKED_CAST")
if (modelClass.isAssignableFrom(CardViewModel::class.java)) {
return CardViewModel(application) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
Main activity with viewmodel init and calling view model
val viewModel = ViewModelProvider(this).get(CardViewModel::class.java)
viewModel.getTextApi("my-api-key", "en-en", "policeman")
viewModel.myResponse.observe(this, Observer { response ->
if(response.isSuccessful) {
response.body()?.forEach {
Log.e("Response", it.text)
}
}else{
Log.e("Response", "CANNOT_LOAD_DATA")
}
And error code
java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:350)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:80)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:39)
at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:27)
at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:225)
at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:121)
at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@c4dedaa, Dispatchers.Main.immediate]