Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to create a simple recyclerView in Kotlin, but the adapter is not applying properly

I'm trying to create a simple recyclerView in Kotlin with data that I get via Volley (which I have confirmed returns the correct data), I keep running to the error E/RecyclerView: No adapter attached; skipping layout when in fact I have specified an adapter with the custom adapter class that I created:

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
}

}

This is my MainActivty class, where I make the actual call for the JSON and attempt to attach my adapter with my ArrayList that I have created:

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)
}
}

I have created a custom data class Image which stores three fields: the imageUrl, submitter and color, all of which are derived from the JSON. I thought that calling notifyDataSetChanged() on my adapter after the request was completed would allow the recyclerView to get updated and show the items, but nothing at all shows up on the screen. Does anyone have any idea as to where I messed up?

like image 975
rakeshdas Avatar asked Mar 25 '17 05:03

rakeshdas


People also ask

How do I create a recycler view adapter in Kotlin?

Go to app > java > package name > right-click > New > Kotlin class/file and name that file as CustomAdapter and then click on OK. After this add the code provided below. Comments are added inside the code to understand the code in more detail.

How do I change my RecyclerView adapter?

Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Open build. gradle and add Recycler view & Card view library dependencies. Step 3 − Add the following code to res/layout/activity_main.


4 Answers

You can download the source code from here(Recyclerview In 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)

        }
    }

}

Thanks!

like image 61
Deepshikha Puri Avatar answered Oct 12 '22 19:10

Deepshikha Puri


Look at following example, I think you this can give you an idea.

You can get the example from here : https://github.com/Siddharha/RecyclerviewTest_Kotlin

Main Activity

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)

  }
}

Adapter Class

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
    }
  }
}

Item Class

internal class MyItem {
var name: String? = null
var number: String? = null
}
like image 25
Siddhartha Maji Avatar answered Oct 12 '22 20:10

Siddhartha Maji


try to use Delegate Adapters below is reference link.

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

like image 1
Sanjay Bhalani Avatar answered Oct 12 '22 20:10

Sanjay Bhalani


I have my RecyclerView Adapter which is as follows,

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))
            }
        }
    }
  }
}
like image 1
Saurabh Padwekar Avatar answered Oct 12 '22 19:10

Saurabh Padwekar