Android access view binding val outside onCreate activity

Viewed 2302

I have an activity that has a button. On the button click I want to update text in text view. I want to use ViewBinding instead of the normal findViewById

This is how I created the val binding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    val binding = ActivityMainBinding.inflate(layoutInflater);
    setContentView(binding.root)

    binding.btnRoll.setOnClickListener {
        rollDice()
    }
}

Now in rollDice I want to update the text view but I'm not able to access binding which make sense because its scope is limited to onCreate() , so what is the best practice for this?

  private fun rollDice() {
       val random = Random().nextInt(6) + 1
       binding.txt_random.setText("random")
    }
3 Answers

You have two options.

1. Store in a property

Since the inflated content of Activity is fully bound to it's lifecycle, it's safe to keep the reference as a property

class MainActivity : AppCompatActivity() {
  lateinit var binding: ActivityMainBinding

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    
    binding = ActivityMainBinding.inflate(layoutInflater);
    setContentView(binding.root)

    binding.btnRoll.setOnClickListener {
      rollDice()
    }
  }

  private fun rollDice() {
    val random = Random().nextInt(6) + 1
    binding.txt_random.setText("random")
  }
}

2. Pass the binding to the methods

That's what I usually do, it avoids creating a property where it's not really a necessity

class MainActivity : AppCompatActivity() {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    
    val binding = ActivityMainBinding.inflate(layoutInflater);
    setContentView(binding.root)

    binding.btnRoll.setOnClickListener {
      rollDice(binding)
    }
  }

  private fun rollDice(binding: ActivityMainBinding) {
    val random = Random().nextInt(6) + 1
    binding.txt_random.setText("random")
  }
}

Both options are valid ways to make the binding visible to Activities methods.

Store the binding in an instance variable on the Activity. Then you have access to it from all the methods in the Activity.

As the question has accepted answer and it is already addressed but here is my approach to the viewBinding

    class MainActivity : AppCompatActivity() {
      private val binding by lazy{
         ActivityMainBinding.inflate(layoutInflater)
       }  
    
      override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
    
        binding.btnRoll.setOnClickListener {
          rollDice()
        }
      }
    
      private fun rollDice() {
        val random = Random().nextInt(6) + 1
        binding.txt_random.setText("random")
      }
    }

I go with lazy initialization of binding so that way it is only intitialized if it is required. More you can read about lazy initialization here https://www.baeldung.com/kotlin/lazy-initialization

Related