简体   繁体   中英

KOTLIN: Basic Async / Coroutines

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 and set before continuing to 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)
                }
            })
    }

}

Move your service call out of the Recycler (best into a ViewModel, but can call from Activity or using any other pattern - the main thing, shouldn't be part of the Recycler) and pass the data, when it's received, into the Recycler.

Your ClientDoseListAdapter to accept medicine:

class ClientDoseListAdapter(private val doses: List<Dose>, private val medicine: Medicine)

In your activity, initiate and a call for medicine and observe it - when the data arrives, pass it to the adapter. Assuming you use a view model your code in Activity would look something like this:

viewModel.getMedicine().observe(
                this,
                Observer<Medicine> { medicine ->
                    //assuming doses come from somewhere else
                    adapter = ClientDoseListAdapter(doses, medicine, this)
                    clientDoseRecyclerView.adapter = adapter

                }
        )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM