HelloCW
HelloCW

Reputation: 2255

Why can a val property be changed in Kotlin?

The Code B is a customized RecyclerView apater with radio button.

mCustomAdapter is changed in both fun methodA() and fun methodB() in Code A, so the reference of get () = mCustomAdapter.getSelectedIndex() is changed too, and it means that the val property mySelectedIndex get value from different address.

In my mind, the val property can't be changed, why doesn't the app cause error?

Code A

private lateinit var mCustomAdapter: CustomAdapter

private val mySelectedIndex get () = mCustomAdapter.getSelectedIndex()

private fun methodA(){
  mCustomAdapter= CustomAdapter(allListA)
  mRecyclerView.adapter= mCustomAdapter
  backup(mySelectedIndex)
}


private fun methodB(){
  mCustomAdapter= CustomAdapter(allListB)
  mRecyclerView.adapter= mCustomAdapter
  restore(mySelectedIndex) 
}

Code B

class CustomAdapter (val backupItemList: List<MSetting>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {

    val noRecord=-1
    private var mSelectedIndex = noRecord

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

    fun getSelectedIndex():Int{
        return  mSelectedIndex
    }

    fun setSelectedIndex(index:Int){
        if (index in 0..(backupItemList.size-1) ){
            mSelectedIndex=index
        }
        notifyDataSetChanged();
    }

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

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

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

        fun bindItems(aMSetting: MSetting) {          

            itemView.radioButton.setOnClickListener {
                mSelectedIndex=adapterPosition
                notifyDataSetChanged();
            }

            if(adapterPosition == 0 && mSelectedIndex == noRecord) {            
                itemView.radioButton.isChecked = true
                mSelectedIndex=adapterPosition
            }
            else {
                itemView.radioButton.isChecked =(adapterPosition == mSelectedIndex)
            }
        }

    }

}

Modified

I think the Code DD and Code EE can get the same effect, right?

Code DD

var aImpl = 0
val a: Int get() = aImpl

fun seta(){
    aImpl=5
}

Code EE

var b:Int=0

fun setb(){
    b=5
}

Upvotes: 0

Views: 2042

Answers (3)

Paul Georg Podlech
Paul Georg Podlech

Reputation: 530

When regarding properties the keyword val means that there is no setter for that property, meaning you can't use the assignment operator = with it. It doesn't mean, that the returned value has to be constant over time.

Upvotes: 1

Marko Topolnik
Marko Topolnik

Reputation: 200148

In my mind, the val property can't be changed, why doesn't the app cause error?

You must adjust your intuition.

In Kotlin, val means "read-only property", not "immutable property". Only vals without a custom getter can be considered immutable.

Upvotes: 5

ice1000
ice1000

Reputation: 6569

A val property can return different value every time you call it like this:

private var aImpl = 0
val a: Int get() = aImpl++

Since the return value of mCustomAdapter.getSelectedIndex() is changing, mySelectedIndex is obviously changing.

Upvotes: 1

Related Questions