Kotlin wait for item to be fetched

I am doing a school project.

I have a list with Doses, so I need to fetch data en set text one by one.

Right now I’m getting:

kotlin.UninitializedPropertyAccessException: lateinit property medicine has not been initialized.

So I need to wait till the first item is fetched, before continuing to set text and continuing to the next item.
can you help me?

class ClientDoseListAdapter(private val doses: List<Dose>) : RecyclerView.Adapter<ClientDoseListAdapter.ViewHolder>() {

    private lateinit var medicine : Medicine

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.client_dose_listitem, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = doses[position]

        runBlocking {
            displayMedicine(item.medicine)

        }

        holder.med_name.text = medicine.name
        holder.dose_amount.text = item.amount.toString()

    }

    private suspend fun displayMedicine(id: Int) {
        fetchMedicine(id)
    }

    override fun getItemCount(): Int = doses.size

    inner class ViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView),
        LayoutContainer


    private fun fetchMedicine(id: Int) {
        service.getMedicine(id, "Bearer ${ClienOverzichtFragment.auth}")
            .enqueue(object : Callback<List<Medicine>> {
                override fun onResponse(call: Call<List<Medicine>>, response: Response<List<Medicine>>) {
                    if (response.code() == 200) {
                        val temp = response.body()!!
                        medicine = temp[0]
                        Log.v("SHIT", medicine.name)
                    } else {
                        Log.v("SHIT", response.code().toString())
                        //TODO
                    }
                }

                override fun onFailure(call: Call<List<Medicine>>, t: Throwable) {
                    Log.v("SHIT", "FAILED : "+t.message)
                }
            })
    }

}

“Checking whether a lateinit var is initialized” explains how to check how something is initialized.

But I don’t think that’s the root of your problem.

It seems to me that you don’t really need to “wait … before … continuing to the next item” but that you do need to know when all the items’ text have been set or a failure to fetch means that some will never be set.

Maybe lateinit is not the right tool for the job here. Maybe this class doesn’t really need a var medicine. Something that is lateinit probably shouldn’t never be initialized due to non-exceptional problems like network failures.

1 Like

What you’re trying to do is block the main thread for every item in a list while you make a network request. If your code actually did what you’re trying to do, the user would almost certainly see an Application Not Responding error.

(The reason you’re getting the UninitializedPropertyAccessException is that fetchMedicine() starts the network request on a background thread and immediately returns, before the request has finished.)

The simplest solution is probably to request all the medicine data before you even show the list, maybe at the same time you get the list of doses. That way you know the data is available for display.

1 Like