1

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]
Spectator
  • 332
  • 1
  • 11

0 Answers0