8 votes

J'essaie de créer un simple recyclerView en Kotlin, mais l'adaptateur ne s'applique pas correctement.

J'essaie de créer un simple recyclerView en Kotlin avec des données que je reçois via Volley (qui, je l'ai confirmé, renvoie les données correctes), mais je tombe toujours sur l'erreur suivante E/RecyclerView: No adapter attached; skipping layout alors qu'en fait j'ai spécifié un adaptateur avec la classe d'adaptateur personnalisée que j'ai créée :

class ImageAdapter(var c: Context, var list: ArrayList<Image>) : RecyclerView.Adapter<ImageAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder? {
    val layoutInflater = LayoutInflater.from(parent.context)
    return ViewHolder(layoutInflater.inflate(R.layout.image_cardview, parent, false))
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val imageUrl = list[position].url
    val submitter = list[position].submitter
    val color = list[position].color
    holder.submitterTV.text = submitter
    holder.card.setCardBackgroundColor(Color.parseColor(color))
}

override fun getItemCount() = list.size
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
    val card = itemView.card
    val submitterTV = itemView.submitter
    val imageView = itemView.image
}

}

C'est ma classe MainActivty, où je fais l'appel réel pour le JSON et où j'essaie d'attacher mon adaptateur avec ma ArrayList que j'ai créée :

class MainActivity : AppCompatActivity() {
val images = ArrayList<Image>()
override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    imageList.layoutManager = LinearLayoutManager(applicationContext)
    request("https://api.unsplash.com/photos/curated/?client_id=API_KEY")
    imageList.adapter = ImageAdapter(applicationContext, images)

}

private fun request(url: String) {
    val queue = Volley.newRequestQueue(this)
    val stringRequest = JsonArrayRequest(url, Response.Listener<JSONArray> { response ->
        try {
            for (i in 0..(response.length() - 1)) {
                val image: Image = Image(response.getJSONObject(i).getJSONObject("urls").getString("full"), response.getJSONObject(i).getJSONObject("user").getString("username"), response.getJSONObject(i).getString("color"))
                images.add(image)
            }

            imageList.adapter.notifyDataSetChanged()

        } catch (e: JSONException) {
            e.printStackTrace()
        }
    }, Response.ErrorListener { })
    queue.add(stringRequest)
}
}

J'ai créé une classe de données personnalisée Image qui stocke trois champs : l'imageUrl, l'expéditeur et la couleur, qui sont tous dérivés du JSON. Je pensais qu'appeler notifyDataSetChanged() sur mon adaptateur après que la requête ait été complétée permettrait à la recyclerView d'être mise à jour et d'afficher les articles, mais rien du tout ne s'affiche à l'écran. Quelqu'un a-t-il une idée de l'endroit où je me suis trompé ?

14voto

Deepshikha Puri Points 999

Vous pouvez télécharger le code source à partir d'ici( Recyclerview en Kotlin Android )

MainActivity.kt :

package com.deepshikha.recyclerviewkotlin
import android.app.Activity
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import android.view.Window
import android.view.WindowManager
import android.widget.LinearLayout
import kotlinx.android.synthetic.main.activity_main.*
import net.simplifiedcoding.recyclerviewexample.CustomAdapter

class MainActivity : Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        requestWindowFeature(Window.FEATURE_NO_TITLE)
        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)

        setContentView(R.layout.activity_main)

        val users = ArrayList<Model_Details>()
        users.add(Model_Details("Kaju katli", "Kaju katli, also known as kaju Katari or kaju barfi, is an Indian dessert similar to a barfi.",R.drawable.kaju))
        users.add(Model_Details("Doughnut", "The doughnut is popular in many countries and prepared in various forms as a sweet snack that can be homemade or purchased in bakeries, supermarkets, food stalls, and franchised specialty outlets",R.drawable.donuts))
        users.add(Model_Details("Panna cotta", "Panna cotta is an Italian dessert of sweetened cream thickened with gelatin and molded. The cream may be aromatized with rum, coffee, vanilla, or other flavorings.",R.drawable.panna_cotta))
        users.add(Model_Details("Rose Cookies", "Rose cooky is a famous South Indian snack made during festivals",R.drawable.rosecookies))
        users.add(Model_Details("Belgian waffle", "In North America, Belgian waffles are a variety of waffle with a lighter batter, larger squares, and deeper pockets than ordinary American waffles",R.drawable.belgianwaffle))

        val obj_adapter = CustomAdapter(users)

        recyclerView.layoutManager = LinearLayoutManager(this, LinearLayout.VERTICAL, false)
        recyclerView.adapter = obj_adapter
    }

}

CustomAdapter.kt :

package net.simplifiedcoding.recyclerviewexample

import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.deepshikha.recyclerviewkotlin.Model_Details
import com.deepshikha.recyclerviewkotlin.R
import kotlinx.android.synthetic.main.adapter_details.view.*

class CustomAdapter(val userList: ArrayList<Model_Details>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {

    //this method is returning the view for each item in the list
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomAdapter.ViewHolder {
        val v = LayoutInflater.from(parent.context).inflate(R.layout.adapter_details, parent, false)
        return ViewHolder(v)
    }

    //this method is binding the data on the list
    override fun onBindViewHolder(holder: CustomAdapter.ViewHolder, position: Int) {
        holder.bindItems(userList[position])
    }

    //this method is giving the size of the list
    override fun getItemCount(): Int {
        return userList.size
    }

    //the class is hodling the list view
    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        fun bindItems(user: Model_Details) {
            itemView.tv_name.text=user.name
            itemView.tv_des.text=user.des
            itemView.iv_name.setImageResource(user.image)

        }
    }

}

Merci !

4voto

Sid Points 396

Regardez l'exemple suivant, je pense que cela peut vous donner une idée.

Vous pouvez obtenir l'exemple ici : https://github.com/Siddharha/RecyclerviewTest_Kotlin

Activité principale

class MainActivity : AppCompatActivity() {
private var myAdapter: MyAdapter? = null
private var arrayList: ArrayList<MyItem>? = null
private var layoutManager: RecyclerView.LayoutManager? = null
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    initialize()
    setupList()
    loaddata()
}

private fun loaddata() {

    for (i in 0..9) {
        val myItem = MyItem()
        myItem.name = "Sid_" + i
        myItem.number = "098899876" + i
        arrayList!!.add(myItem)
    }

    myAdapter!!.notifyDataSetChanged()

}

private fun setupList() {
    rlItems!!.layoutManager = layoutManager
    rlItems!!.adapter = myAdapter
}

private fun initialize() {
    arrayList = ArrayList<MyItem>()
    layoutManager = LinearLayoutManager(this, LinearLayout.VERTICAL, false)
    myAdapter = MyAdapter(arrayList!!, this, R.layout.item_cell)

  }
}

Classe d'adaptateur

internal class MyAdapter(private val arrayList: ArrayList<MyItem>,
                     private val context: Context,
                     private val layout: Int) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {

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

override fun onBindViewHolder(holder: MyAdapter.ViewHolder, position: Int) {
    holder.bindItems(arrayList[position])
}

override fun getItemCount(): Int {
    return arrayList.size
}

internal inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

    fun bindItems(items: MyItem) {
        itemView.tvName.text = items.name
        itemView.tvNumber.text = items.number
    }
  }
}

Classe d'article

internal class MyItem {
var name: String? = null
var number: String? = null
}

1voto

Sanjay Bhalani Points 680

Essayez d'utiliser les adaptateurs de délégué ci-dessous est le lien de référence.

Lien Ref : https://Android.jlelse.eu/keddit-part-4-recyclerview-delegate-adapters-data-classes-with-kotlin-9248f44327f7

0voto

Saurabh Padwekar Points 1136

J'ai mon adaptateur RecyclerView qui est le suivant,

internal class OptionsAdapter : RecyclerView.Adapter<OptionsAdapter.ViewHolder>() {

private val mOptionList = ArrayList<Option>()
private var mOnItemClickListener: OnItemClickListener<Option>? = null

var data: List<Option>
    get() = mOptionList
    set(list) {
        mOptionList.clear()
        mOptionList.addAll(list)
        notifyDataSetChanged()
    }

fun setOnItemClickListener(listener: OnItemClickListener<Option>) {
    mOnItemClickListener = listener
}

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

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val option = getItem(position)
    holder.textViewOption.setText(option.text)
    holder.textViewDescription.setText(option.subText)
}

private fun getItem(index: Int): Option {
    return mOptionList[index]
}

override fun getItemCount(): Int {
    return mOptionList.size
}

internal inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    var textViewOption: TextView
    var textViewDescription: TextView
    var imageViewOptionIcon: ImageView

    init {
        textViewOption = itemView.findViewById<TextView>(R.id.textview_option)
        imageViewOptionIcon = itemView.findViewById<ImageView>(R.id.imageview_option_icon)
        textViewDescription = itemView.findViewById<TextView>(R.id.textview_description)
        itemView.setOnClickListener {
            if (mOnItemClickListener != null) {
                mOnItemClickListener!!.onItemClick(getItem(adapterPosition))
            }
        }
    }
  }
}

0voto

iOS Lifee Points 513

Sur .MainActivity.kt

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    //rcv is id of Recyclerview
    rcv.layoutManager = LinearLayoutManager(this)
    rcv.adapter = MyAdpater()
}

Créer un nouveau fichier .kt pour créer l'adaptateur

class MyAdpater : RecyclerView.Adapter<ViewHolder>() {
val arr = listOf("A", "B", "C", "D", "E") //static array
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.textView.setText(arr.get(position)) //set text to textview by position
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    return ViewHolder(TextView(parent.context))
 }

override fun getItemCount(): Int {
    return arr.count() //return array count
}}

class ViewHolder(val textView: TextView): RecyclerView.ViewHolder(textView){ //ViewHolder with textview}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X