Issue
I ran into the same problem today while launching the app.I really appreciate your help in solving my problem. Api and JSON - https://swapi.dev/api/people/
Below is the error code:
Error
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.skreep.starwarsappandroid, PID: 20521
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:40)
at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:27)
at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:243)
at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:153)
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:919)
This is the code Model
data class Characters(
@SerializedName("name")
val characters: String,
@SerializedName("gender")
val gender: String
)
This is code model (List Characters)
class CharacterList: ArrayList<Characters>()
This is code my ViewModel
class HomeViewModel() : ViewModel() {
var repository = StarWarsRepository()
val list: MutableLiveData<Response<CharacterList>> = MutableLiveData()
fun getCharacterViewModel() {
viewModelScope.launch {
list.value = repository.getCharacters()
}
}
}
This is code my interface
@GET("people/")
suspend fun getCharacters(): Response<CharacterList>
This is code my Fragment
class HomeFragment : Fragment() {
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
private lateinit var viewModel: HomeViewModel
lateinit var recyclerView: RecyclerView
private lateinit var adapter: HomeListAdapter
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
viewModel = ViewModelProvider(this)[(HomeViewModel::class.java)]
_binding = FragmentHomeBinding.inflate(inflater, container, false)
val view = binding.root
recyclerView = binding.recycler
adapter = HomeListAdapter()
recyclerView.layoutManager= LinearLayoutManager(requireContext())
recyclerView.adapter = adapter
getCharacterViewModel()
return view
}
private fun getCharacterViewModel(){
viewModel.getCharacterViewModel()
viewModel.list.observe(this, { list ->
list.body()?.let { adapter.setList(it) }
})
}
}
Adapter
package com.skreep.starwarsappandroid.ui.fragments.home.adapter
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.skreep.starwarsappandroid.data.remote.model.Characters
import com.skreep.starwarsappandroid.databinding.ItemCharacterBinding
class HomeListAdapter() :
RecyclerView.Adapter<HomeListAdapter.HomeViewHolder>() {
var peopleList = emptyList<Characters>()
class HomeViewHolder(var binding: ItemCharacterBinding) :
RecyclerView.ViewHolder(binding.root) {
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeViewHolder {
return HomeViewHolder(
ItemCharacterBinding.inflate(
LayoutInflater
.from(parent.context), parent, false
)
)
}
override fun onBindViewHolder(holder: HomeViewHolder, position: Int) {
val characterList = peopleList[position]
holder.binding.characterName.text = characterList.characters
holder.binding.characterGender.text = characterList.gender
}
override fun getItemCount(): Int {
return peopleList.size
}
@SuppressLint("NotifyDataSetChanged")
fun setList(list: List<Characters>) {
peopleList = list
notifyDataSetChanged()
}
}
Solution
You need to create additional model to parse json into, for example call it CharactersResponse
and use it in request function instead of CharacterList. So it will look like the following:
data class CharactersResponse(
@SerializedName("results")
val charactersList: CharacterList
)
@GET("people/")
suspend fun getCharacters(): Response<CharactersResponse>
You missed the results
object from json representation, where characters are stored:
{
"count": 82,
"next": "https://swapi.dev/api/people/?page=2",
"previous": null,
"results": [ ...
Answered By - Sergey
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.