43

I have been using findViewById and then ButterKnife to bind views. Recently, I came across this article and am not quite sure how to use it.

I tried doing it but it does not seem to work in Android Studio 3.4.2

val binding = MainActivityBinding.inflate(layoutInflater)
setContentView(binding.root)

then afterwards using these values, as an example :

binding.button....
binding.textView....
Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
siera
  • 443
  • 1
  • 4
  • 6
  • Do you wrap xml in tag and enable databindin in gradle? – Amirhosein Jul 19 '19 at 17:50
  • I am not because its mentioned in the article that its not required - "generating a databinding class requires wrapping the layout file into a special layout tag. For ViewBinding changes to the layout file are not required" – siera Jul 19 '19 at 17:53
  • ok but you have to enabe it in gradle. – Amirhosein Jul 19 '19 at 17:58
  • here is a useful article that explains everything about view binding https://proandroiddev.com/new-in-android-viewbindings-the-difference-from-databinding-library-bef5945baf5e – Rainmaker Sep 25 '19 at 13:56
  • Hi I have written a blog post completely explaining view binding checkout [Androidbites|ViewBinding](https://chetangupta.net/viewbinding/) – Chetan Gupta Dec 06 '20 at 10:45

12 Answers12

69

There is a couple of things you should do and I try to make it organized and listed: (Based on Android Developers docs from this link and my personal experiences)

  1. You need to use Android Studio 3.6 canary11+ (I'm currently using Android Studio 4 and it is doing the job well for me)

    You can find it from here: https://developer.android.com/studio/archive

  2. You need to upgrade your Gradle wrapper to Gradle "5.6.4" and Gradle build tool to "3.6.0-rc01", higher versions also work so don't be afraid to be updated

    distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
    dependencies {

        ...
        classpath 'com.android.tools.build:gradle:3.6.0-rc01'

    }
  1. To enable view binding in a module, add the viewBinding element to its build.gradle file, as shown in the following example:
    android {
    ...
      viewBinding {
        enabled = true
      }
    }
  1. If you want a layout file to be ignored while generating binding classes, add the tools:viewBindingIgnore="true" attribute to the root view of that layout file:
    <LinearLayout
        ...
        tools:viewBindingIgnore="true" >
        ...
    </LinearLayout>
  1. If view binding is enabled for a module, a binding class is generated for each XML layout file that the module contains. Each binding class contains references to the root view and all views that have an ID. The name of the binding class is generated by converting the name of the XML file to camel case and adding the word "Binding" to the end.

    For example, given a layout file called result_profile.xml:

    <LinearLayout ... >
        <TextView android:id="@+id/name" />
        <ImageView android:cropToPadding="true" />
        <Button android:id="@+id/button"
            android:background="@drawable/rounded_button" />
    </LinearLayout>

The generated binding class is called ResultProfileBinding. This class has two fields: a TextView called name and a Button called button. The ImageView in the layout has no ID, so there is no reference to it in the binding class.

Every binding class also includes a getRoot() method, providing a direct reference for the root view of the corresponding layout file. In this example, the getRoot() method in the ResultProfileBinding class returns the LinearLayout root view.

  1. To set up an instance of the binding class for use with an activity, fragment or card view adapter perform the following steps:
  • in the activity's onCreate() method:
    private ResultProfileBinding binding;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    binding = ResultProfileBinding.inflate(getLayoutInflater());
    View view = binding.getRoot();
    setContentView(view);
}
  • in the fragments's onCreateView() method:
    private FragmentHousesBinding binding;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        binding = FragmentHousesBinding.inflate(inflater, container, false);

        init();

        return binding.getRoot();
    }
  • in the card view adapter's onCreateViewHolder() method:
    HouseCardPropertyFragmnetBinding binding;

    @Override
    public Holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        binding = HouseCardPropertyFragmnetBinding.inflate(LayoutInflater
            .from(parent.getContext()), parent, false);

        return new Holder(binding);
    }

    @Override
    public void onBindViewHolder(@NonNull HouseAdapter.Holder holder, int position) {
        holder.bindData(getItem(position));
    }

    class Holder extends RecyclerView.ViewHolder {

        HouseCardPropertyFragmnetBinding view;

        Holder(@NonNull HouseCardPropertyFragmnetBinding v) {
            super(v.getRoot());
            view = v;
        }

        void bindData(Tag item) {
            view.tagTxt.setText(item.Name);

        }
    }

that's it you are free from the findViewById from now on ;)

SowlM
  • 892
  • 7
  • 10
  • @SowIM in your answer, how would onBindViewHolder() look? – portfoliobuilder Feb 26 '20 at 01:45
  • 1
    @portfoliobuilder I edited my answer and added onBindViewHolder() to the adapter part. – SowlM Feb 26 '20 at 15:49
  • Good list, one small thing where I'm not sure what to use, for ViewHolders there are 2 possibilities, the one you mentioned in the adapter and a second one: `this.binding = SomeViewHolderBinding.bind(itemView);` in the viewholder constructor directly not sure which of these is the better option tbh. additionally for custom views here is how: `this.binding = ViewSomeNameBinding.inflate(LayoutInflater.from(context), this, true);` cheers – Finn Marquardt Feb 27 '20 at 08:20
  • 1
    If you have list items whose width should `match_parent`, you should modify the `onCreateViewHolder(@NonNull ViewGroup parent, int viewType)` method: change `binding = ListItemBinding.inflate(LayoutInflater.from(parent.getContext()));` for `binding = ListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);`. My list items stopped being full width because I didn't specify the parameters when inflating the list item views. Interestingly, though, when there was a `MaterialCardView` in my `list_item.xml`, the list items _were_ full width even without the additional params. – Vratislav Jindra Mar 04 '20 at 09:30
  • Such an underrated answer.. deserves more! Works perfect on `AS 3.6`. – sanjeev Mar 12 '20 at 09:42
13

In most cases, view binding replaces findViewById.

Java: Add this in Gradle file

android {
...
    buildFeatures {
        viewBinding true
    }
}

Kotlin

android {
    ...
    buildFeatures {
        viewBinding = true
    }
}

If you want a layout file to be ignored while generating binding classes, add the tools:viewBindingIgnore="true" attribute to the root view of that layout file:

<LinearLayout
    ...
    tools:viewBindingIgnore="true" >
    ...
</LinearLayout>

Use view binding in activities

Kotlin

private lateinit var binding: ResultProfileBinding
    
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ResultProfileBinding.inflate(layoutInflater)
    val view = binding.root
    setContentView(view)
}

Java

private ResultProfileBinding binding;
    
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    binding = ResultProfileBinding.inflate(getLayoutInflater());
    View view = binding.getRoot();
    setContentView(view);
}

You can now use the instance of the binding class to reference any of the views:

Kotlin

binding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }

Java

binding.getName().setText(viewModel.getName());
binding.button.setOnClickListener(new View.OnClickListener() {
    viewModel.userClicked()
});

view binding in fragments

Kotlin

private var _binding: ResultProfileBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
    
override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
    ): View? {
        _binding = ResultProfileBinding.inflate(inflater, container, false)
        val view = binding.root
        return view
    }
    
override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}

Java

private ResultProfileBinding binding;
    
@Override
public View onCreateView (LayoutInflater inflater,
                              ViewGroup container,
                              Bundle savedInstanceState) {
    binding = ResultProfileBinding.inflate(inflater, container, false);
    View view = binding.getRoot();
    return view;
}
    
@Override
public void onDestroyView() {
    super.onDestroyView();
    binding = null;
}

You can now use the instance of the binding class to reference any of the views:

Kotlin

kotlinbinding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }

Java

binding.getName().setText(viewModel.getName());
binding.button.setOnClickListener(new View.OnClickListener() {
    viewModel.userClicked()
});
Omnibyte
  • 361
  • 6
  • 18
Rehan Khan
  • 1,031
  • 13
  • 10
12

View binding is only available in Android Studio 3.6 Canary 11+. Firstly, you upgrade Android studio with android gradle plugin version 3.6.0-alpha11+ (you can use beta both of them for now, stable version not yet released but you can use beta) then add below code in build.gradle

android {
        viewBinding.enabled = true
}

Now you can use like we used with data binding like that:

private lateinit var binding: ActivityMainBinding

@Override
fun onCreate(savedInstanceState: Bundle) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)

    binding.textView.text = "Hello World"
}

that's it.

ankuranurag2
  • 2,300
  • 15
  • 30
Umut ADALI
  • 1,146
  • 1
  • 14
  • 31
9

ViewBinding is only available from Android Studio 3.6 and above

1:- You need to upgrade your gradle build toold to 3.6.1 in build.gradle (Project level)

 dependencies {
        classpath 'com.android.tools.build:gradle:3.6.1'
             }

2:- You need to enable viewBinding in build.gradle(app)

 android {
viewBinding {
    enabled = true
}}

Once view binding is enabled a binding class is generated for each XML layout. The name of the binding class is generated by converting the name of the XML file to camel case and adding the word "Binding" to the end.

Example:- if a layout file is named as "add_item_activity.xml" then the Name of Binding class will be "AddItemActivityBinding"

3:-To set up an instance of the binding class for use with an activity, create a instance of Binding class, here we will create instance of "AddItemActivityBinding" and will call the static inflate method generated in the binding class

Get a reference to the root view by calling the getRoot() method and pass this root view in setContentView() method

public class AddItemActivity extends AppCompatActivity {
    private AddItemActivityBinding binding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = AddItemActivityBinding.inflate(getLayoutInflater());
        View view = binding.getRoot();
        setContentView(view);

        //now we can access views by their IDs 
        binding.tvTitleMyOrder.setText("Title goes here");

    }

}

Now we can access views by their IDs using instance of binding class

tushar
  • 315
  • 4
  • 6
5

:--------------------------------------This is for Kotlin--------------------------------------:

You need to follow two steps:

1) Add viewBinding in your project's Module:

buildFeatures{
        viewBinding true
    }

enter image description here

2) Add binding to your Activity Class:

private lateinit var binding: ActivitySplashBinding

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

enter image description here

Abubakar Khalid
  • 109
  • 2
  • 5
4

ViewBindings are introduced at this moment of this talk at Google IO/19. It will be available with Android Studio 3.6 and as you mentioned, you're using Android Studio 3.4.2 so it's not working. Read the ViewBindings portion in this article for more references.

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
SaadAAkash
  • 3,065
  • 3
  • 19
  • 25
  • 1
    Thanks for the info. Is there an alternative for Butterknife with the new Androidx?? – siera Jul 19 '19 at 18:29
  • Kotlin Synthetics should work just fine. But please go through this link before using it instead of Butter/KotterKnife: https://proandroiddev.com/the-argument-over-kotlin-synthetics-735305dd4ed0. And please accept my answer by clicking the right tick mark on the left since it should be the only reason why it was not working. I'd appreciate it. – SaadAAkash Jul 19 '19 at 18:58
  • Using synthetics doesn't require all that including tags or annotations like Butter/KotterKnife: https://gist.github.com/krossovochkin/d1fa52746843666257fc23d73749a4dc#file-synthetics-kt – SaadAAkash Jul 19 '19 at 19:00
  • Is there any alternative in Java? Am not using kotlin – siera Jul 19 '19 at 20:01
  • You used kotlin code snippet in the question which is why I assumed you're developing in Kotlin. For java, I'm afraid you need to stick to data binding with ButterKnife. – SaadAAkash Jul 19 '19 at 20:13
2

View Binding ViewBinding is available from Android Studio 3.6 and above

  1. It is used to bind the views to the code in other words we can simply say it replaces findViewById in android which reduces the boilerplate code.

  2. we can use view binding whenever you inflate layouts such as Fragment, Activity, or RecyclerView Adapter.

  3. Once view binding is enabled it will automatically generate a binding class for all the XML layouts in android project and no needed to make any changes in our xml layouts manually.

  4. We can enable view binding in the module-level build.gradle

    android {
    ...
    buildFeatures {
    viewBinding true
    }
    }

activity_simple_view_binding_example.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".SimpleViewBindingExample">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:id="@+id/demoTv"/>


</LinearLayout>

SimpleViewBindingExample.java

public class SimpleViewBindingExample extends AppCompatActivity {

    private ActivitySimpleViewBindingExampleBinding activitySimpleViewBindingExampleBinding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        activitySimpleViewBindingExampleBinding = ActivitySimpleViewBindingExampleBinding.inflate(getLayoutInflater());
        setContentView(activitySimpleViewBindingExampleBinding.getRoot());

        activitySimpleViewBindingExampleBinding.demoTv.setText("View Binding is simple");

    }
}
Rohit S
  • 714
  • 5
  • 7
2

in kotlin

The important note is view binding is only available for android studio 3.6+. implement view binding in the project you can follow the below steps.

Step 1: upgrade your Gradle version(3.6.1+) in the build.gradle (Project Level) file.

   dependencies {
            classpath 'com.android.tools.build:gradle:7.0.3' 
    }

Step 2: Add this line to your build.gradle (App Level) file in android{}

 buildFeatures {
        viewBinding = true
    }

Step 3: Add this code (Depend on Your Activity name).

class MainActivity : AppCompatActivity() {

 private lateinit var binding: ActivityMainBinding

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

    binding = ActivityMainBinding.inflate(layoutInflater)
    val view = binding.root //you can use directly setContentView(binding.root)
    setContentView(view) 
    binding.textview.text="Hii" 

}

or you can achieve the above functionality in this code. I personally prefer to goes to the second one.

class MainActivity : AppCompatActivity() {

    private val binding by lazy {

        ActivityMainBinding.inflate(layoutInflater)
    }


   override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
        binding.textview.text="Hii" 

    }
}
Ronik Limbani
  • 667
  • 4
  • 5
1

As a beginner, If you want to learn to implement the Data Binding in your Android project.

then simply follow these steps:-

1:- First open up your Gradel Scripts Folder and locate build.gradel Module file and paste this code inside android project.

 dataBinding {
        enabled = true
    }

plugins {
    id 'com.android.application'
    id 'kotlin-android'
}

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.3"

    defaultConfig {
        applicationId "com.example.implementing_data_binding"
        minSdkVersion 19
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    dataBinding {
        enabled = true
    }
}

dependencies {

    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.2'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.3.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
    implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

then simply in your XML file encapsulate your current layout in a new parent layout tag and shift name-space declaration from current layout to newly created parent layout

<?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">
    
<androidx.coordinatorlayout.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/myId"
        android:layout_width="wrap_content"
        android:layout_height="34dp"
        android:layout_marginLeft="150sp"
        android:layout_marginTop="300sp"
        android:text="Hello world!" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>

2:- Go to your view and assign an id to it:- android:id="@+id/textHere"

3:- Then simply go inside your corresponding activity file and below the Activity class initialization put

lateinit var binding: ActivityMainBinding;

Note- the word ActivityMainBinding is just a combination of your file where the view exists along with the + 'Binding'

ex:- File name: acvity_main.kt -------> ActivityMainBinding

And inside the onCreate function just below the super constructor call put

    binding = androidx.databinding.DataBindingUtil.setContentView(this,R.layout.activity_main);

Here- R.layout.activity_main is the name of the file where the view exists

package com.example.implementing_data_binding

import android.os.Bundle
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import androidx.appcompat.app.AppCompatActivity
import android.view.Menu
import android.view.MenuItem
import com.example.implementing_data_binding.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    lateinit var binding: ActivityMainBinding;
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = androidx.databinding.DataBindingUtil.setContentView(this,R.layout.activity_main);
//        setContentView(R.layout.activity_main)
        binding.myId.text = "Yup its done!";
    }

}

Now you are able to access the properties of that view.

try binding.myId.text = "Yup its done!";

Note:- myId is the name of my id we defined in view

Sujeet Mishra
  • 199
  • 3
  • 2
0

From Android studio 3.6 canary11+ u can use ViewBinding. For reference see this link

Karthick Ramanathan
  • 642
  • 3
  • 9
  • 20
0

I recommend use like this:

private val viewBinding: ADarkModeBinding by lazy { ADarkModeBinding.inflate(layoutInflater) }

override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   setContentView(viewBinding.root)
}
Marek Kondracki
  • 1,372
  • 2
  • 8
  • 13
-1

In case you're using Kotlin, all you have to do is add this plugin:

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'kotlin-android-extensions' <--
}
Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121