A.Fish
A.Fish

Reputation: 143

Populate multiple fields in one line in Kotlin

I would like to know if it's possible to populate multiple fields in one line in Kotlin (just for cleaner code)

My Code:

val evh = ExampleViewHolder(binding.root)
evh.mImageView = binding.myImageView
evh.mTextView1 = binding.text1
evh.mTextView2 = binding.text2

I would like to achieve something like this:

(evh.mImageView, evh.mTextView1, evh.mTextView2) = (binding.myImageView, binding.text1, binding.text2)

Is this somewhat possible?

Upvotes: 3

Views: 1427

Answers (4)

Max
Max

Reputation: 788

You could also pass views as arguments to ExampleViewHolder, like this:

class ExampleViewHolder(
    val rootView: View, val imageView: ImageView, 
    val textView1: TextView, val textView2: TextView
) : RecyclerView.ViewHolder(rootView) {...}

And then instantiate the ViewHolder using the apply scope function:

val viewHolder = binding.run {
    ExampleViewHolder(root, myImageView, text1, text2)
}

Upvotes: 2

alexrnov
alexrnov

Reputation: 2534

If an object has already been created, to change several fields you can use scope function "run", like:

evh.run { 
    mImageView = binding.myImageView 
    mTextView1 = binding.text1
    mTextView2 = binding.text2 
}

Upvotes: 1

jsamol
jsamol

Reputation: 3232

is this somewhat possible?

No, you can't set properties* in such a way in Kotlin.

If you'd like to initialize or change values on some properties in a cleaner way, you can use one of the scope functions:

The Kotlin standard library contains several functions whose sole purpose is to execute a block of code within the context of an object. When you call such a function on an object with a lambda expression provided, it forms a temporary scope. In this scope, you can access the object without its name. Such functions are called scope functions. There are five of them: let, run, with, apply, and also.

In this particular case it seems like apply is the best fit:

val evh = ExampleViewHolder(binding.root).apply {
    mImageView = binding.myImageView
    mTextView1 = binding.text1
    mTextView2 = binding.text2
}

*note that similar inline syntax is valid in Kotlin and it's used in destructing declarations:

val (first, second) = listOf("firstValue", "secondValue")

Upvotes: 5

Bram Stoker
Bram Stoker

Reputation: 1232

I found this post which says it's possible if you put all views in a data class:

data class ExampleViewHolder(val mImageView: ImageView, val mTextView: TextView, val mTextView2: TextView, val binding: Binding) : RecyclerView.ViewHolder(binding.root)

and then do something like this:

val (mImageView, mTextView1, mTextView2, binding) = ExampleViewHolder(binding.myImageView, binding.text1, binding.text2, binding)

Alternatively you can always put semi-columns in between assignments to one-line it, but it does not get more readable imo:

evh.mImageView = binding.myImageView; evh.mTextView1 = binding.text1; evh.mTextView2 = binding.text2

I would just assign the fields inside your ExampleViewHolder:

class ExampleViewHolder(binding: Binding) : RecyclerView.ViewHolder(binding.root) {
    val mImageView = binding.myImageView
    val mTextView = binding.text1
    val mTextView2 = binding.text2
}

Or even let the ExampleViewHolder do the binding:

class ExampleViewHolder(val binding: Binding) : RecyclerView.ViewHolder(binding.root) {

    fun bindTo(item: Any) {
        binding.myImageView.visibility = View.GONE
    }
}

Upvotes: 1

Related Questions