I'm writing an application for currencies. Empty data is received (Json is normal). I tried to debug it, but I didn’t understand where and what the error was. I would be grateful if you can help me understand where the error or errors are. Here's my code:
ApiService:
interface ApiService {
@GET("daily_json.js")
suspend fun getValute(): Response<Valute>
}
RetrofitInstance:
object RetrofitInstance {
private val retrofit by lazy {
Retrofit.Builder().baseUrl("https://www.cbr-xml-daily.ru/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
val api: ApiService by lazy {
retrofit.create(ApiService::class.java)
}
}
Repository:
class Repository {
suspend fun getVal(): Response<Valute>{
return RetrofitInstance.api.getValute()
}
}
ViewModel:
class StartViewModel: ViewModel() {
var repo = Repository()
val moneyList: MutableLiveData<Response<Valute>> = MutableLiveData()
fun getMoney(){
viewModelScope.launch {
moneyList.value = repo.getVal()
}
}
}
Fragment:
class StartFragment : Fragment() {
private lateinit var _binding: FragmentStartBinding
private val binding get() = _binding!!
private val adapter = StartAdapter()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentStartBinding.inflate(inflater, container, false)
val view = binding.root
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.rvStart.adapter = adapter
val viewModel = ViewModelProvider(this).get(StartViewModel::class.java)
viewModel.getMoney()
viewModel.moneyList.observe(viewLifecycleOwner,{list ->
list.body()?.let { adapter.setList(it) }
})
}
Adapter:
class StartAdapter: RecyclerView.Adapter<StartAdapter.StartHolder>() {
var listValute = emptyList<Valute>()
class StartHolder(item: View): RecyclerView.ViewHolder(item) {
val binding = ItemBinding.bind(item)
fun bind(valute: Valute) = with(binding){
nameMoney.text = valute.CharCode
purchase.text = valute.Value.toString()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StartHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false)
return StartHolder(view)
}
override fun getItemCount(): Int {
return listValute.size
}
override fun onBindViewHolder(holder: StartHolder, position: Int) {
holder.bind(listValute[position])
}
fun setList(valute: Valute){
listValute = listOf(valute)
notifyDataSetChanged()
}
}
I'm attaching all the code you might need.
Update I forgot to add DataClass
data class Valute(
val CharCode: String,
val ID: String,
val Name: String,
val Nominal: Int,
val NumCode: String,
val Previous: Double,
val Value: Double
): Serializable
Your data model does not match what is returned from the API.
Your Valute
(data) class is an element of the map (which is under key "Valute").
So first create a generic model for the answer, for example something like this:
data class ValuteResponse(
@SerializedName("Date")
val date: String,
@SerializedName("PreviousDate")
val previousDate: String,
@SerializedName("PreviousURL")
val previousURL: String,
@SerializedName("Timestamp")
val timestamp: String,
@SerializedName("Valute")
val valute: Map<String, Valute>,
)
Here in model class I use com.google.gson.annotations.SerializedName
annotation to indicate what the field is called in the received response (JSON).
Then use it (in ApiService
) as a response model from the API:
@GET("daily_json.js")
suspend fun getValute(): Response<ValuteResponse>
There are many websites that can create classes for you from your existing JSON: