I've been following this tutorial here about how to perform view Binding, and nothing seems to work properly, but first it doesn't seem to generate the new class file after modding the module gradle file, like it says it will.
First, I'm not sure how to do the gradle setup. With my browsing of the internet and developer blogs I've come across three different versions of how to put it:
android {
...
buildFeatures {
viewBinding = true
}
or like:
android {
...
buildFeatures {
viewBinding{
enabled = true
}
}
or maybe like:
android {
...
viewBinding {
enabled = true
}
And I've built (or "made", as it were) the project with all of those and nothing seems to happen. I know that the associated layout class file, which, in this case, is just a standard set of layout and class files that comes with making a default project with an empty Activity, is supposed to "generate" a class file that's the name of its associated layout file, written in Pascal format with "Binding" tacked on the end, thus, in this case, the layout file is called activity_main.xml
, so the class file should therefore be MainActivityBinding
(which, I know is backwards, but that's how they had it by default: MainActivity
)
So then, after that, there's supposed to be a getroot()
method to every file in the module that allows binding. But it don't get that either. In fact most of the code mentioned here doesn't work. I get unreferenced variable errors all over the place, which probably stems from the file not generating properly, but I don't really know.
I've got a lot more problems with this set of directions Google gives you, but if this is the main problem, I'll just start here.
So how do I fix this? What am I really supposed to do?
UPDATE: I figured out, through and error, that this is what I'm supposed to put in the gradle file (note: it would not accept viewbinding instead of databinding)
android {
...
buildFeatures.dataBinding = true
But the new file did not generate. What should I do?
activity_main.xml
:
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Also, inb4, here's MainActivity.kt
:
package com.example.bindtestbinding
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
Alright, so after a lot of trial and error, this is what worked for me:
I named mine "BindTest"
(Now, you may not have to start all over, but I took no chances)
It generated a "MainActivity" class file and an "activity_main.xml" layout file, along with its layout folder
At the child level of the Android
block, add this:
buildFeatures.dataBinding = true
The following didn't work, and the error suggested I change it to the above (And this is what they suggest on the official documentation site!):
buildFeatures{
viewBinding{
enabled=true
}
}
In activity_bind.xml
:
Exchange androidx.constraintlayout.widget.ConstraintLayout
with simply layout
Remove the following from the layout (Else, you'll get an error saying there's a duplicate of one of them when you add another layout inside):
android:layout_width="match_parent"
android:layout_height="match_parent"
Remove default TextView
and add a Linear Layout (or some other layout)
(I removed this because the Design Window was being a way when I tried to add a Linear Layout without deleting it. If you can do it, more power to you, and tell me your dark secrets.)
Throw in some TextView
s and give them IDs
tv1
, tv2
, and tv3
It should generate ActivityBindBinding
class (I regret my nomenclature decisions), but it does NOT rename the class file associated with the layout file; it merely does it under the covers. To actually see if what you did worked...
BindActivity
Classprivate lateinit var binding: ActivityBindBinding
onCreate
:
binding = ActivityBindBinding.inflate(layoutInflater)
after the super
callsetContentView
to be binding.root
You should now be allowed to use the IDs directly (binding.tv1
)
onCreate
, last line:
binding.tv1 = "Hello from inside the class"
When I ran the app after doing all this, it worked.
Don't know about you, but arrays in Kotlin are a pain to me, so I tested them to make sure I got this right.
onCreate
, remove the last line we made and call to two methods. It should look like this: override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
initTextViews() //these two
setTextViews() //right chere
}
private fun initTextViews() {
textViews = arrayOf(
binding.tv1,
binding.tv2,
binding.tv3
)
}
private fun setTextViews() {
textViews.forEachIndexed { ind, tv ->
tv.text = values[ind].toString()
}
}
I ran the app again: SUCCESSSSSSSSSSS!!
I'd like to point out that, when I tried to make a project with No Activity, it didn't work properly, claiming that there was "no Default Activity set". So, if you want to save yourself from some headache (Because this is enough), just start with an Empty Activity...please