I was experimenting View Binding in my new app. Suddenly today when I run the app it displays blank white screen instead of UI. If I remove binding and use setContentView, it works!
Any idea why this is happening?
Code:
build.gradle
viewBinding {
enabled = true
}
MainActivity
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
}
You need to call setContentView with ViewBinding as:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root) // add this
}
Related
The code I wrote is not working because viewbinding is not suitable. I got some help from my friend but I still couldn't do the application please help me my application is interrupted
/*MainActivity*/
class MainActivity : AppCompatActivity() {
private var _binding: ActivityMainBinding?=null//
private val binding
get()=_binding!!
override fun onCreate(savedInstanceState: Bundle?) {
_binding=ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.apply{ //5.işlemimiz ;)
editText
}
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
fun aktiviteDegistir (view:View){
val kullaniciVerisi = editText.text.toString()
val intent = Intent(applicationContext,IkinciActivity::class.java)
intent.putExtra("yollananVeri",kullaniciVerisi)
startActivity(intent)//activiteyi başlatım güzel yer
}
/*Activity2*/
val intent = intent//intent
val alinanVeri = intent.getStringExtra("yollananVeri")
textView2.text = alinanVeri
class MainActivity : AppCompatActivity() {
private var _binding: ActivityMainBinding?=null//3.islemimiz
private val binding
get()=_binding!!
override fun onCreate(savedInstanceState: Bundle?) {//4.işlemiiz
_binding=ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.apply{ //5.işlemimiz ;)
editText
}
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
After adding this code, I waited for the messages to go away, but they didn't.
my application will write something about this to the editText button will be pressed then it needs to come to the textview part in the other activity
you are following approach, that is used to bind in fragment binding. The problem is that you are setting the binding data but not connecting it with the content view. for better approach in activity view binding just the same for more cleaner activity binding.
class MainActivity : AppCompatActivity() {
private lateinit var binder : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binder = ActivityMainBinding.inflate(layoutInflater)
setContentView(binder.root)
viewImpl()
}
/**you view calls...
* like button.setonclick() and all UI related interactions...
*/
private fun viewImpl() {
binder.run {
//here...
}
}
}
In here I have created binding lateinit var for activity binder which will be initialise when binder = ActivityMainBinding.inflate(layoutInflater) and then using that binder reference for setting my content view as setContentView(binder.root).
Happy Coding ✌️.
My questions is relatively simple: How does the binding find the layout to my Main Actvity since I don't use the ID, I use the name "root". And how am I going to find different layouts to my other screens using the similar code?
MAIN ACTIVITY
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var binding: ActivityMainBinding = ActivityMainBinding.inflate(layoutInflater) // variable binding to access layout views
setContentView(binding.root) // here define o XML
}
}
I'm new to view binding. I haven't found a good resource to study it yet.
The ActivityMainBinding is not named ActivityMainBinding because you use it in the MainActivity. It's generated based on a layout file that is named activity_main so technically you are using specific ID but not via layout resource.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var binding: ActivityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
}
is exactly the same as:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
without the utility of data binding ofc.
Once you have a layout that uses data binding structure, the binding is automatically generated. e.g. for layout activity_second there will be ActivitySecondBinding.
i'am a newest in android kotlin
I want to know what is the difference between the two lines of code below and which one is better to use
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMaindinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
bindins = DataBindingutil.setContentview( this, R.layout.activity_main)
textview.text="text"//or
binding.textview.text="text"
}}
TL;DR There are a few ways of getting views - using view binding is the currently recommended method.
View Binding (recommended)
The recommended way of accessing views is to use view binding. It offers a few advantages over getting the views manually
Less boilerplate code (you don't need to write a bunch of findViewById calls)
Null safety (catches errors like trying to access views from the wrong layout at build time instead of run time)
Type safety - the type of each view is set to help avoid invalid casts
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
// or, without using DataBindingUtil
// binding = ActivityMainBinding.inflate(layoutInflater)
// setContentView(binding.root)
binding.textview.text="text"
}
}
Manually Getting Views
The old way also still works - you can always call findViewById yourself. Keep in mind that it may error or return null if the view is not found or if you try to cast it to the wrong type.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textview = findViewById<TextView>(R.id.textview)
textview.text="text"
}
}
Kotlin Synthetics (deprecated)
Kotlin synthetics were introduced in 2017 to make it easier to get views, but are now deprecated and should be replaced with view binding. With synthetics you would have an import with your layout file name, then you could just access views from it directly.
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
textview.text="text"
}
}
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")
}
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
How to initialize VievBinding? In AppCompactActivity version 1.0.0, it became possible to pass a layout to the parent constructor so that you would not write OnCreateView.
I do so, but then I want to use VievBinding, but it doesn’t work for me. Text is not displayed. What can be done?
class MainActivity : AppCompatActivity(R.layout.activity_main) {
override fun onStart() {
super.onStart()
var binding = ActivityMainBinding.inflate(layoutInflater)
binding.hello.text = "Hello"
}
}
class MainActivity : AppCompatActivity(R.layout.activity_main) {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.bind(findViewById(Window.ID_ANDROID_CONTENT).getChildAt(0))
}
Although it's easier if you rely on __Binding.inflate().
class MainActivity : AppCompatActivity {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater, R.layout.activity_main)
setContentView(binding.root)
}
Layout inflation should not be in onStart. It goes in onCreate in Activity, and onCreateView in Fragment.
// Activity class
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState);
val binding:YourActivityLayoutBinding =
DataBindingUtil.setContentView(this, R.layout.your_activity_layout);
}
Layout views in xml should be surrounded by <layout> tag
<layout>
...// your activity view layout
</layout>
var binding = ActivityMainBinding.inflate(layoutInflater)
This will inflate the layout again and you will get a different instance of the views than what is already set in the activity
Try using the below code to bind the activity view to the binder. Where ROOT_VIEW_ID is view id of root view in your layout
var binding = ActivityMainBinding.bind(findViewById(ROOT_VIEW_ID))*
*binding.hello.text = "Hello"