How I can avoid using findViewById
in my app. Layout is very complicated and findViewById
traverses its tree to find view which takes time and it is used several times.
First, you must edit your application’s build.gradle
file and add the following into the android block:
android {
…
dataBinding.enabled = true
}
The next thing is to change the layout file by making the outer tag instead of whatever ViewGroup you use:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<TextView
android:id="@+id/hello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
</layout>
The layout tag tells Android Studio that this layout should take the extra processing during compilation time to find all the interesting Views and note them for the next step. All layouts without that outer layout tag will not get the extra processing step, so you can sprinkle these into new projects wherever you like without changing anything in the rest of your application.
The next thing you have to do is to tell it to load your layout file differently at runtime. Because this works all the way back to the Eclair release, there is no reliance on new framework changes to load these preprocessed layout files. Therefore, you do have to make a slight change to your loading procedure.
From an Activity, instead of:
setContentView(R.layout.hello_world);
TextView hello = (TextView) findViewById(R.id.hello);
hello.setText("Hello World"); // for example, but you'd use resources, right?
You load it like this:
HelloWorldBinding binding = DataBindingUtil.setContentView(this, R.layout.hello_world);
binding.hello.setText("Hello World"); // you should use resources!
Here you can see that a class, HelloWorldBinding
, was generated for the hello_world.xml
layout file, and the View with the ID @+id/hello
was assigned to a final field hello
that you can use. No casting, no findViewById
.
It turns out that this mechanism for accessing views is not only much easier than findViewById
, but can also be faster! The binding process makes a single pass on all Views in the layout to assign the views to the fields. When you run findViewById
, the view hierarchy is walked each time to find it.
One thing you will see is that it transforms your variable names into camel case (just like hello_world.xml
becomes the class HelloWorldBinding
), so if you gave it the ID @+id/hello_text
, then the field name would be helloText
.
When you’re inflating your layouts for RecyclerView
, ViewPager
, or other things that aren’t setting the Activity contents, you’ll want to use the generated type-safe methods on the generated class. There are several versions that match the LayoutInflater
, so use the one that is most appropriate for your use. For example:
HelloWorldBinding binding = HelloWorldBinding.inflate(
getLayoutInflater(), container, attachToContainer);
If you aren’t attaching the inflated View to the containing ViewGroup
, you’ll have to get access to the inflated View hierarchy. You can do this from the getRoot()
method of the binding:
linearLayout.addView(binding.getRoot());
Another choice is Kotlin's Android extensions.
// Using R.layout.activity_main from the main source set
import kotlinx.android.synthetic.main.activity_main.*
class MyActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Instead of findView(R.id.textView) as TextView
textView.setText("Hello, world!")
}
}
https://kotlinlang.org/docs/tutorials/android-plugin.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With