1

So I know this is code heave but I'm having issues getting my RecyclerView in a Fragment sorted out. i've read a bunch of tutorial and everyone seems to have a different way of doing things. Just not able to nail it down...So here is my code:

FRAGMENT XML

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.xxxx.listview.CalendarFragment">    

    <android.support.v7.widget.RecyclerView
        android:id="@+id/event_recycle"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="horizontal" />
</FrameLayout>

DATA CLASS

data class SectionOrRow(var needTicketing:String?,var eventSponsor:String?,var eventED:String?,var eventSD:String?,var eventTitle:String?,var mysectionName:String?,var isRow:Boolean){

    companion object {

        public fun createRow(row: String): Unit {
           // val ret = SectionOrRow()
         //   return ret
        }

        public fun createSection(section: String): Unit {
           // val ret = SectionOrRow(null,section,false)
           // return ret
        }
    }
}

FRAGMENT CLASS

package com.example.XXX.listview




class CalendarFragment : Fragment() {
    lateinit var eventInfo: JsonArray<JsonObject>
    lateinit var event2Info: JsonArray<JsonObject>
    val eventList0 = ArrayList<SectionOrRow>()    
    val TAG : String= "CalendarFragment"

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {

        val view : View = inflater.inflate(R.layout.fragment_calendar,container,false)
        (activity as MainActivity).getSupportActionBar()?.setTitle("Medfield Calendar")
        var event_recycle:RecyclerView = view.findViewById(R.id.event_recycle)


        var myUrl:String = "https://www.nosite.com/functions/API/eventsJSON2.php?zip_code=02052"
        myUrl.httpGet().responseString { request, response, result ->
            //do something with response
            when (result){
                is Result.Failure -> {
                    Log.d("Towns",result.toString())
                    val error = result.getAs<String>()
                    Log.d("Towns error ",error)
                }
                is Result.Success -> {

                    val data = result.getAs<String>()
                    val events : Parser = Parser()
                    val eventBuilder: StringBuilder  = StringBuilder(data)
                    val eventsjson = events.parse(eventBuilder) as JsonObject

                    Log.d("JOO",eventsjson.toString())

                    var eventList0 = ArrayList<SectionOrRow>()


                    eventInfo  = eventsjson.array("events")!!

                    Log.d("length array",this.eventInfo.size.toString())
                    if(this.eventInfo.size<2){
                        Toast.makeText(context,"There are no categories for this town...", Toast.LENGTH_LONG).show()
                    }else{

                        Log.d("type",this.eventInfo.javaClass.name) // kotlin.Double
                        for (i in eventInfo.indices){



                            //Log.d("Loops"+i.toString(),eventInfo[i].string("category"))
                            //Log.d("Loops"+i.toString(),eventInfo[i].string("events2"))
                            var theCat = eventInfo[i].string("category")
                            eventList0.add(SectionOrRow(null,null,null,null,null,theCat,false))


                            var theEvents:JsonArray<JsonObject>? = eventInfo[i].array("events2")
                            Log.d("MSG1","IS category header"+theCat)
                            theEvents?.let{
                                for(x in theEvents.indices){
                                    val needT: String? = theEvents[x].string("news_needsticketing")
                                    val eventSpon: String? = theEvents[x].string("news_sponsor")
                                    val startD: String? = theEvents[x].string("news_start_date")
                                    val endD: String? = theEvents[x].string("news_expiration")
                                    val newsT: String? = theEvents[x].string("news_tile")

                                    eventList0.add(SectionOrRow(needT,eventSpon,endD,startD,newsT,theCat,true))
                                }
                                Log.d("MSG2","Are Events")
                            }

                            //eventList0.add(SectionOrRow.createRow("City"))
                        }


                    }

                    event_recycle.layoutManager = LinearLayoutManager(context)
                    event_recycle.hasFixedSize()
                    event_recycle.adapter = MyEventAdapter(context,eventList0)
                    Log.d("All Size First",eventList0.size.toString())



                    //Log.d("FN",nextOne.toString())
                    // myview.textView3.setText(Html.fromHtml(ownerMessage,Html.FROM_HTML_MODE_LEGACY))
                    //myview.textView3.setText(myCS)

                }
            }
        }

        // Inflate the layout for this fragment
        return view

    }

    inner class MyEventAdapter(context: Context,val theEvents:ArrayList<SectionOrRow>):RecyclerView.Adapter<RecyclerView.ViewHolder>(){

        override fun getItemViewType(position: Int): Int {
            if(theEvents[position].isRow){
                return 0
            }else{
                return 1
            }


        }

        override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
            val item = theEvents.get(position)

            if(item.isRow){
                val h = holder as RowViewHolder
                h.textView.setText(item.mysectionName)
            }else{
                val h = holder as SectionViewHolder
                h.textView.setText(item.eventSD)
            }

        }



        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder? {

            if(viewType==0) {
                val v = LayoutInflater.from(parent.context).inflate(R.layout.calendar_row, parent, false)
                return RowViewHolder(v)
            }

            if(viewType==1){
                val v = LayoutInflater.from(parent.context).inflate(R.layout.calendar_section, parent, false)
                return SectionViewHolder(v)
            }
            return null
        }

        override fun getItemCount(): Int {
                Log.d("All Size",theEvents.size.toString())
                return theEvents.size
        }


        inner class RowViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            val textView: TextView

            init {
                textView = itemView.findViewById<View>(R.id.sectionHead) as TextView
            }
        }

        inner class SectionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            val textView: TextView

            init {
                textView = itemView.findViewById<View>(R.id.dateOfEvent) as TextView
            }
        }

    }

}

The error which I'm getting it that:

10-10 09:12:49.239 32612-32612/com.example.xxxx.listview E/RecyclerView: No adapter attached; skipping layout

SO it appears that I'm not able to attach the adapter to the recycler view. sure there are other errors but this is problem one ;)

SOLUTION

 inner class MyEventAdapter(context: Context,val theEvents:ArrayList<SectionOrRow>):RecyclerView.Adapter<RecyclerView.ViewHolder>(){

        override fun getItemViewType(position: Int): Int {
            Log.d("Current Boolean",theEvents[position].isRow.toString())

            if(theEvents[position].isRow){
                //true is row
                return 1
            }else{
                return 0
            }


        }

        override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
            val item = theEvents.get(position)
            Log.d("Current Item",item.toString())

            if(item.isRow){
                val h = holder as RowViewHolder

                val s = java.text.SimpleDateFormat("EEE\nMM/dd")
                val format = s.format(Integer.parseInt(item.eventSD) * 1000L)

                h.textView.setText(format)
                Log.d("Current Title",item.eventTitle.toString())

                h.titleView.setText(item.eventTitle)
                h.datesView.setText(item.eventED)
                h.sponsorView.setText(item.eventSponsor)
                if(item.needTicketing=="Y") {
                    h.ticketView.setText("Ticketing Available")
                }else{
                    h.ticketView.setText("")

                }
            }else{
                val h = holder as SectionViewHolder
                h.textView.setText(item.mysectionName)
            }

        }



        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder? {

            if(viewType==1) {
                val v = LayoutInflater.from(parent.context).inflate(R.layout.calendar_row, parent, false)

                v.setOnClickListener(object: View.OnClickListener {
                    override fun onClick(p0: View?) {
                        Toast.makeText(
                                v.context,
                                "Please Click Set Town to Return to Previous Screen....",
                                Toast.LENGTH_SHORT
                        ).show()

                    }
                })
                return RowViewHolder(v)
            }

            if(viewType==0){
                val v = LayoutInflater.from(parent.context).inflate(R.layout.calendar_section, parent, false)
                return SectionViewHolder(v)
            }
            return null
        }

        override fun getItemCount(): Int {
                Log.d("All Size",theEvents.size.toString())
                return theEvents.size
        }


        inner class RowViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            var textView: TextView
            var titleView: TextView
            var datesView: TextView
            var sponsorView: TextView
            var ticketView: TextView

            init {
                textView = itemView.findViewById<View>(R.id.dateOfEvent) as TextView
                titleView = itemView.findViewById<View>(R.id.rowTitle) as TextView
                datesView = itemView.findViewById<View>(R.id.rowDates) as TextView
                sponsorView = itemView.findViewById<View>(R.id.rowSponsor) as TextView
                ticketView = itemView.findViewById<View>(R.id.rowTicketing) as TextView

            }
        }

        inner class SectionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            var textView: TextView
            init {
                textView = itemView.findViewById<View>(R.id.sectionHead) as TextView
            }
        }



    }
BostonMacOSX
  • 1,369
  • 2
  • 17
  • 38

3 Answers3

2

call your RecyclerViewAdapter class in override fun onViewCreated in your Fragment

override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    val recyclerView=view?.findViewById(R.id.your_recycler_view) as RecyclerView
    recyclerView.layoutManager=LinearLayoutManager(context, LinearLayout.VERTICAL,false)
    var yourData=ArrayList<YourDataClass>()
    yourData.add(YourDataClass("passYourData"))


    val yourAdapterClassVariableName=YourRecyclerViewAdapterClass(yourData)
    recyclerView.adapter=yourAdapterClassVariableName
}
MSpeed
  • 8,153
  • 7
  • 49
  • 61
Ganger
  • 91
  • 3
  • 10
0

You need to set your adapter in the UI thread. Initialize your adapter first, then add the data to it and call adapter.notifyDataSetChanged().

I'd also direct you to kotlin extensions (importing synthetic properties section) so you don't have to call that messy findViewById call anymore.

airowe
  • 794
  • 2
  • 9
  • 29
0

Please see the top for the solution to this issue... was an issue of getting the right types into the right rows.

BostonMacOSX
  • 1,369
  • 2
  • 17
  • 38