mercredi 23 août 2023

Only last item in RecyclerView gets updated when notifyDataSetChanged is called

I want to build a segment wise list with selection feature. For this I have multiple RecyclerViews (for e.g. 5) in my layout file and the data list of each recyclerview is dynamic.As you can see in this image

Now, each item in recyclerview has a checkbox. What I need to do is when user selects any item, only those items of that perticular list should be enabled and other segment's list items should be disabled.

The issue I am facing is when I am trying to update each recyclerview using notifyDataSetChanged, only last item in the list is disabled and rest are enabled. I debugged the app, and process wise everything is working fine but the app doesn't reflect the same.As you can see here

My data model -

data class SelectionModel(
    var channelType: String,
    var channelName: String,
    var devices: ArrayList<SelectiveDevice>?
) {
    data class SelectiveDevice(
        var deviceName: String,
        var deviceType: String,
        var selected: Boolean = false
    )
}

My MainActivity -

class MainActivity : AppCompatActivity(), FiveChannelDeviceAdapter.FiveChannelDeviceCallback, FourChannelDeviceAdapter.FourChannelDeviceCallback, ThreeChannelDeviceAdapter.ThreeChannelDeviceCallback, TwoChannelDeviceAdapter.TwoChannelDeviceCallback, OneChannelDeviceAdapter.OneChannelDeviceCallback {

    lateinit var mBinding: ActivityMainBinding
    private var segments = ArrayList<SelectionModel>()

    private lateinit var fiveChannelDeviceAdapter: FiveChannelDeviceAdapter
    private lateinit var fourChannelDeviceAdapter: FourChannelDeviceAdapter
    private lateinit var threeChannelDeviceAdapter: ThreeChannelDeviceAdapter
    private lateinit var twoChannelDeviceAdapter: TwoChannelDeviceAdapter
    private lateinit var oneChannelDeviceAdapter: OneChannelDeviceAdapter

    var selectedType = ""
    var selectedGroup = ""
    var countChecked = 0
    var devices5ch = ArrayList<SelectionModel.SelectiveDevice>()
    var devices3ch = ArrayList<SelectionModel.SelectiveDevice>()
    var devices1ch = ArrayList<SelectionModel.SelectiveDevice>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        fiveChannelDeviceAdapter = FiveChannelDeviceAdapter(this@MainActivity, this@MainActivity)
        fourChannelDeviceAdapter = FourChannelDeviceAdapter(this@MainActivity, this@MainActivity)
        threeChannelDeviceAdapter = ThreeChannelDeviceAdapter(this@MainActivity, this@MainActivity)
        twoChannelDeviceAdapter = TwoChannelDeviceAdapter(this@MainActivity, this@MainActivity)
        oneChannelDeviceAdapter = OneChannelDeviceAdapter(this@MainActivity, this@MainActivity)

        mBinding.rvFiveCh.adapter = fiveChannelDeviceAdapter
        mBinding.rvFourCh.adapter = fourChannelDeviceAdapter
        mBinding.rvThreeCh.adapter = threeChannelDeviceAdapter
        mBinding.rvTwoCh.adapter = twoChannelDeviceAdapter
        mBinding.rvOneCh.adapter = oneChannelDeviceAdapter

        segments.clear()
        devices5ch.clear()
        devices3ch.clear()
        devices1ch.clear()

        val device1 = SelectionModel.SelectiveDevice("First", "5ch", false)
        val device2 = SelectionModel.SelectiveDevice("Second", "5ch", false)
        val device3 = SelectionModel.SelectiveDevice("Third", "5ch", false)
        val device4 = SelectionModel.SelectiveDevice("Forth", "3ch", false)
        val device5 = SelectionModel.SelectiveDevice("Fifth", "3ch", false)
        val device6 = SelectionModel.SelectiveDevice("Sixth", "1ch", false)

        devices5ch.add(device1)
        devices5ch.add(device2)
        devices5ch.add(device3)

        devices3ch.add(device4)
        devices3ch.add(device5)

        devices1ch.add(device6)

        val segment5ch = SelectionModel("5ch", "Color & CCT Lights", devices5ch)
        val segment3ch = SelectionModel("3ch", "Color Lights", devices3ch)
        val segment1ch = SelectionModel("1ch", "White Lights", devices1ch)

        segments.add(segment5ch)
        segments.add(segment3ch)
        segments.add(segment1ch)

        fiveChannelDeviceAdapter.setAdapterData(segments[0].devices!!, selectedType, selectedGroup, countChecked)
        threeChannelDeviceAdapter.setAdapterData(segments[1].devices!!, selectedType, selectedGroup, countChecked)
        oneChannelDeviceAdapter.setAdapterData(segments[2].devices!!, selectedType, selectedGroup, countChecked)

    }

    override fun resetSelection() {
        selectedType = ""
        selectedGroup = ""
        countChecked = 0

        fiveChannelDeviceAdapter.setAdapterData(segments[0].devices!!, selectedType, selectedGroup, countChecked)
        threeChannelDeviceAdapter.setAdapterData(segments[1].devices!!, selectedType, selectedGroup, countChecked)
        oneChannelDeviceAdapter.setAdapterData(segments[2].devices!!, selectedType, selectedGroup, countChecked)
    }

    override fun setReverseData(
        selectedType: String,
        selectedGroup: String,
        countChecked: Int,
        deviceList: ArrayList<SelectionModel.SelectiveDevice>
    ) {
        this.selectedType = selectedType
        this.selectedGroup = selectedGroup
        this.countChecked = countChecked
        val alteredList = java.util.ArrayList<SelectionModel>()
        alteredList.addAll(segments)

        for (group in alteredList) {
            if (group.channelType.equals(this.selectedType, true)) {
                group.devices = deviceList
            }
        }

        fiveChannelDeviceAdapter.setAdapterData(alteredList[0].devices!!, selectedType, selectedGroup, countChecked)
        threeChannelDeviceAdapter.setAdapterData(alteredList[1].devices!!, selectedType, selectedGroup, countChecked)
        oneChannelDeviceAdapter.setAdapterData(alteredList[2].devices!!, selectedType, selectedGroup, countChecked)

    }
}

One of the Adapter -

class FiveChannelDeviceAdapter(
    private val context: Context,
    private val callback: FiveChannelDeviceCallback
) :
    RecyclerView.Adapter<FiveChannelDeviceAdapter.FiveChannelDeviceViewHolder>() {

    private var mDeviceLists = ArrayList<SelectionModel.SelectiveDevice>()
    private lateinit var channelDevices: LayoutChannelDeviceBinding

    var selectedTypes = ""
    var selectedGroups = ""
    var countCheckeds = 0

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

        fun setData(position: Int) {
            if (countCheckeds > 0) {
                if (mDeviceLists[position].deviceType == selectedTypes) {
                    Log.d("SegmentSelected", position.toString())
                    channelDevices.selectDeviceCheck.setOnCheckedChangeListener(null)
                    channelDevices.selectDeviceCheck.isEnabled = true
                    channelDevices.selectDeviceCheck.isClickable = true
                    channelDevices.selectDeviceCheck.isChecked = mDeviceLists[position].selected
                    channelDevices.tvDeviceName.text = "Enabled"
                } else {
                    Log.d("SegmentNotSelected", position.toString())
                    channelDevices.selectDeviceCheck.isEnabled = false
                    channelDevices.selectDeviceCheck.isClickable = false
                    channelDevices.tvDeviceName.text = "Disabled"
                }
            } else {
                Log.d("SegmentReset", position.toString())
                channelDevices.selectDeviceCheck.isEnabled = true
                channelDevices.selectDeviceCheck.isClickable = true
                channelDevices.tvDeviceName.text = "Enabled"
            }

            channelDevices.selectDeviceCheck.setOnCheckedChangeListener { compoundButton, checked ->
                if (checked) {
                    countCheckeds += 1
                    mDeviceLists[position].selected = checked
                    selectedTypes = mDeviceLists[position].deviceType
                    selectedGroups = selectedTypes
                    Log.d("DeviceList", mDeviceLists.toString())
                    callback.setReverseData(selectedTypes, selectedGroups, countCheckeds, mDeviceLists)
                } else if (countCheckeds > 0 && !checked) {
                    countCheckeds -= 1
                    mDeviceLists[position].selected = checked
                    if (countCheckeds == 0) {
                        countCheckeds = 0
                        selectedTypes = ""
                        selectedGroups = ""
                        callback.resetSelection()
                    } else {
                        callback.setReverseData(selectedTypes, selectedGroups, countCheckeds, mDeviceLists)
                    }
                } else if (countCheckeds == 0 && !checked) {
                    countCheckeds = 0
                    mDeviceLists[position].selected = checked
                    selectedTypes = ""
                    selectedGroups = ""
                    callback.resetSelection()
                }
            }

        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FiveChannelDeviceViewHolder {
        channelDevices = LayoutChannelDeviceBinding.inflate(
            LayoutInflater.from(parent.context),
            parent,
            false
        )
        return FiveChannelDeviceViewHolder(channelDevices.root)
    }

    override fun onBindViewHolder(holder: FiveChannelDeviceViewHolder, position: Int) {
        holder.setData(position)
    }

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

    fun setAdapterData(mDeviceList: ArrayList<SelectionModel.SelectiveDevice>, selectedType: String, selectedGroup: String, countChecked: Int) {
        this.mDeviceLists.clear()
        this.mDeviceLists.addAll(mDeviceList)
        this.selectedTypes = selectedType
        this.selectedGroups = selectedGroup
        this.countCheckeds = countChecked
        notifyDataSetChanged()
    }

    interface FiveChannelDeviceCallback {
        fun resetSelection()
        fun setReverseData(selectedType: String, selectedGroup: String, countChecked: Int, deviceList: ArrayList<SelectionModel.SelectiveDevice>)
    }
}



Aucun commentaire:

Enregistrer un commentaire