I’m working with an API that gets a list of holidays “https://date.nager.at/api/v3/PublicHolidays/2024/”.
I have a spinner with 5 items that are countries abbreviated. Ideally, when the user selects an item, I need to get that text and append it to the API link (https://date.nager.at/api/v3/PublicHolidays/2024/US), and whenever the user selects a different country from the spinner, it will update the API link and fetch holidays for the selected country.
I’ve set the default API to “US” because the base url doesn’t return anything unless you add a country at the end. My code is running but when I choose other countries from the spinner, API link doesn’t update.
Any help is appreciated.
My MainActivity.kt
private lateinit var binding : ActivityMainBinding
private lateinit var holidayAdapter: HolidayAdapter
private lateinit var holidayList : List<Holiday>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
this.binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(this.binding.root)
// Initialize holidayAdapter
holidayAdapter = HolidayAdapter(emptyList())
binding.holidayRecyclerView.adapter = holidayAdapter
binding.holidayRecyclerView.layoutManager = LinearLayoutManager(this)
// Set up spinner
binding.countrySpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
val selectedCountry = parent?.getItemAtPosition(position).toString()
connectToAPI(selectedCountry)
}
override fun onNothingSelected(parent: AdapterView<*>?) {
// Do nothing
}
}
}
private fun connectToAPI(countryCode: String) {
val holidayAPI: API = RetrofitInstance.createAPI()
lifecycleScope.launch {
val response = holidayAPI.getAllHolidays(countryCode)
val apiHolidayList: List<Holiday> = response
holidayAdapter.setItems(apiHolidayList)
Log.d("MainActivity", "Holiday List: $apiHolidayList")
}
}
My API.kt
interface API {
@GET("{countryCode}")
suspend fun getAllHolidays( @Path("countryCode") countryCode: String): List<Holiday>
}
My RetrofitInstance.kt:
object RetrofitInstance {
// Base URL without the year and country code
private const val BASE_URL = "https://date.nager.at/api/v3/PublicHolidays/2024/"
private val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
// Custom Retrofit Builder to handle dynamic URLs
private val retrofitBuilder = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(MoshiConverterFactory.create(moshi))
// Function to create the Retrofit service with dynamic base URL
fun createAPI(): API {
val retrofit = retrofitBuilder.build()
return retrofit.create(API::class.java)
}
}
My HolidayAdapter.kt
class HolidayAdapter(private var holidayList: List<Holiday>) : RecyclerView.Adapter<HolidayAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.holiday_item, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val holiday = holidayList[position]
holder.bind(holiday)
// Add space between items except for the last item
val marginBottom = if (position < holidayList.size - 1) {
holder.itemView.resources.getDimensionPixelSize(R.dimen.item_bottom_margin)
} else {
0 // No margin for the last item
}
val layoutParams = holder.itemView.layoutParams as ViewGroup.MarginLayoutParams
layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin, layoutParams.rightMargin, marginBottom)
holder.itemView.layoutParams = layoutParams
}
override fun getItemCount(): Int {
return holidayList.size
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val holidayNameTextView: TextView = itemView.findViewById(R.id.holidayNameTextView)
private val holidayLocalNameTextView: TextView = itemView.findViewById(R.id.holidayLocalNameTextView)
private val holidayDateTextView: TextView = itemView.findViewById(R.id.holidayDateTextView)
fun bind(holiday: Holiday) {
holidayNameTextView.text = holiday.name
holidayLocalNameTextView.text = holiday.localName
holidayDateTextView.text = holiday.date
}
}
// Method to set a new list of items to the adapter
fun setItems(holidays: List<Holiday>) {
holidayList = holidayList + holidays
notifyDataSetChanged()
}
```