0

Hi and thanks for reading in advance, I have built a small project testing an adapter to populate a main activity view with a custom xml template [this template holds some fields that are populated by some simple test data and images inside the project] The build is fine afaik, I have debugged it as best I can to yield no errors and I cant actually find the error as i follow the build in debug so it's likely my noob-like experience with kotlin, android studio and maybe the later development approach changes. My best guess after following it through a few (way more ha) times, at this stage it seemed to be going wrong during the android part of the build versus any prep and adapter code so it could be some settings I havent invoked maybe... Also probably importantly: I saw it pull in the recyclerView during debug(prior to any customisation from the imported xml layout im using), the visual then disappears, but i do see all the code being populated by the functions ive created in MainActivity and the adapter does seem to return to MainActivity with the respective data constructed. I enclose the project zipped as there is no discernable error code or post runtime exit code that i can find [thats not to say there isn't one, I'm newoob to the IDE :( ] I'm targeting an Android 7.0 600*1024 mdpi using API 24 on a 7" (LH flip)portrait orientation x86 emulator

I'm using Android Studio 2021.1.1 patch 3 if that's important to know too

Thanks again for anyone who can take a peek at it to help me along, im proper stuck, been so for couple days now, thinking of a complete redo again :/ :) I enclose a link to the zipped file below [due to no errors in debug to provide here]

[Edit: Cripes I forgot to mention I'm also using CircleImageViewer, not sure if that causing an issue but it doesn't appear to be ]

[Final edit: As can be seen below this was answered by Tyler V who understood my problem better than I could pose the question - please see below for a complete resolution/ refactor of code by them that works correctly - thanks again to Tyler V]

project on googledrive

gruffy321
  • 175
  • 2
  • 13
  • 2
    Open the LogCat tab, run your app (filter by your app in the dropdown to make things easier) and post the full stacktrace it gives you when it crashes (the Error log level should show it). If it's crashing then there *will* be an error logged! If you can't see it, deselect the filtering, and look through the log around the timestamp of when the crash happened - errors should be in yellow or orange. Honestly I don't know if anyone's going to download and build your app (hey they might!) and I'm not really clear on what exactly you're seeing - does it run or doesn't it? – cactustictacs May 02 '22 at 00:42

1 Answers1

2

I took a look at you app, the error it is throwing (look in the Logcat tab!) is this

Process: com.example.kayakthing, PID: 4289
java.lang.IndexOutOfBoundsException: Index: 5, Size: 5
    at java.util.ArrayList.get(ArrayList.java:411)
    at com.example.kayakthing.HiresAdapter.onBindViewHolder(HiresAdapter.kt:34)
    at com.example.kayakthing.HiresAdapter.onBindViewHolder(HiresAdapter.kt:11)

Problem

The reason it is throwing this is because you are supplying different length arrays to your adapter. Take a look at the adapter code below - in your current code the lengths of nameList and clientDetailsList are both 7 but the length of hireImageList is 5. Since you define getItemCount based on the length of nameList - the adapter crashes when trying to show values for positions past the end of the hireImageList size.

override fun onBindViewHolder(holder: HiresViewHolder, position: Int) {
    holder.tvClientName.text = nameList[position]
    holder.tvClientDetails.text = clientDetailsList[position]
    holder.imageView.setImageResource(hireImageList[position])
}

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

Solution

I recommend you 1) learn to read the Logcat tab to find errors, and 2) define a data class to hold the three items you need in your adapter, so you can pass in a single list of that data class instead of three lists. That way there is no way to pass in lists with mis-matched lengths.

For example, use something like this and have the adapter take a single List<HiresAdapter.Data> instead of three lists.

class HiresAdapter(
    private var adapterData: ArrayList<Data>,
    private var context: Context) : RecyclerView.Adapter<HiresAdapter.HiresViewHolder>() {

    // Define a data class in the adapter to hold the data
    // needed for each row
    data class Data(val name: String, val details: String, val image: Int)
    
    class HiresViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var tvClientName : TextView = itemView.findViewById(R.id.tvClientName)
        var tvClientDetails : TextView = itemView.findViewById(R.id.tvClientDetail)
        var imageView : CircleImageView = itemView.findViewById(R.id.hireImageView)
    }

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

    override fun onBindViewHolder(holder: HiresViewHolder, position: Int) {
        holder.tvClientName.text = adapterData[position].name
        holder.tvClientDetails.text = adapterData[position].details
        holder.imageView.setImageResource(adapterData[position].image)
    }

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

and populate it like this

val adapterData = ArrayList<HiresAdapter.Data>()
adapterData.add(HiresAdapter.Data("Geoff",  "Geoff",  R.drawable.solo))
adapterData.add(HiresAdapter.Data("Frogme", "Frogme", R.drawable.tandem))
adapterData.add(HiresAdapter.Data("Jenny",  "Jenny",  R.drawable.quattro))
adapterData.add(HiresAdapter.Data("Benny",  "Benny",  R.drawable.sup))
adapterData.add(HiresAdapter.Data("Sylvia", "Sylvia", R.drawable.croc))

adapter = HiresAdapter(adapterData, this@MainActivity)
Tyler V
  • 9,694
  • 3
  • 26
  • 52
  • Wow, thank you for an entire in-depth resolution to this. firstly, I have taken up the advice [from both contributors ] and now realise the logcat window is where the error party is at, if I have one ,so that's literally an amazing jump to help me finally see whats going on, silly of me to have not clicked it and clearly available in the kotlin language basics, I must of slipped past it in some blurry stupor to get going... – gruffy321 May 02 '22 at 09:38
  • ...I have implemented your solution and it now works gloriously, thank you for this approach change it is an interesting resolve - I now have to study it a little to see how I would best fit this with a CRUD system to assign a new user/ append this new user to the existing recycler view of names. Again cant thank you enough for your quick and detailed response which has 100% answered my questions :)Happy times – gruffy321 May 02 '22 at 09:38