如何在Android中使用视图绑定

时间:2019-07-19 17:41:37

标签: android android-databinding findviewbyid

我一直在使用findViewById,然后使用ButterKnife绑定视图。最近,我碰到了这篇文章:https://proandroiddev.com/new-in-android-viewbindings-the-difference-from-databinding-library-bef5945baf5e,但不确定如何使用。

我尝试这样做,但是在Android Studio 3.4.2中似乎不起作用

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

然后使用这些值作为示例:

binding.button....

binding.textView....

7 个答案:

答案 0 :(得分:25)

这是您应该做的两件事,我尝试将其整理和列出:(基于this link的Android开发者文档以及我的个人经验)

  1. 您需要使用Android Studio 3.6 canary11 +(我目前正在使用Android Studio 4,并且对我来说做得很好)

    您可以在这里找到它: https://developer.android.com/studio/archive

  2. 您需要将Gradle包装器升级到Gradle“ 5.6.4”,并将Gradle构建工具升级到“ 3.6.0-rc01”,更高的版本也可以使用,所以不要害怕被更新

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

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

    }
  1. 要在模块中启用视图绑定,请将viewBinding元素添加到其build.gradle文件中,如以下示例所示:
    android {
    ...
    buildFeatures {
        viewBinding true
    }
}
  1. 如果要在生成绑定类时忽略布局文件,请将tools:viewBindingIgnore="true"属性添加到该布局文件的根视图:
    <LinearLayout
        ...
        tools:viewBindingIgnore="true" >
        ...
    </LinearLayout>
  1. 如果为模块启用了视图绑定,则会为模块包含的每个XML布局文件生成一个绑定类。每个绑定类都包含对根视图和所有具有ID的视图的引用。绑定类的名称是通过将XML文件的名称转换为驼峰大小写并在单词末尾添加“ Binding”来生成的。

    例如,给定一个名为result_profile.xml的布局文件:

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

生成的绑定类称为ResultProfileBinding。此类具有两个字段:一个称为TextView的{​​{1}}和一个名为name的{​​{1}}。布局中的Button没有ID,因此在绑定类中没有对其的引用。

每个绑定类还包括一个button方法,为相应布局文件的根视图提供直接引用。在此示例中,ImageView类中的getRoot()方法返回getRoot()根视图。

  1. 要设置绑定类的实例以与活动,片段或卡片视图适配器一起使用,请执行以下步骤:
  • 在活动的onCreate()方法中:
ResultProfileBinding
  • 在片段的onCreateView()方法中:
LinearLayout
  • 在卡视图适配器的onCreateViewHolder()方法中:
    private ResultProfileBinding binding;

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

就是这样,您从现在开始就没有 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(); } ;)

答案 1 :(得分:4)

ViewBinding仅在Android Studio 3.6及更高版本中可用

1:-您需要在build.gradle(项目级别)中将gradle build toold升级到3.6.1

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

2:-您需要在build.gradle(app)中启用viewBinding

 android {
viewBinding {
    enabled = true
}}

一旦启用视图绑定,就会为每个XML布局生成一个绑定类。绑定类的名称是通过将XML文件的名称转换为驼峰大小写并在单词末尾添加“ Binding”来生成的。

示例:-如果将布局文件命名为“ add_item_activity.xml ”,则绑定类的名称将为“ AddItemActivityBinding

3:-要为活动创建绑定类的实例, 创建Binding类的实例,在这里我们将创建“ AddItemActivityBinding ”的实例,并将调用在绑定类中生成的静态 inflate 方法

通过调用getRoot()方法获取对根视图的引用 并在setContentView()方法中传递此根视图

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");

    }

}

现在,我们可以使用绑定类的实例按其ID访问视图

答案 2 :(得分:1)

在Google IO / 19的本讲座的moment中介绍了

ViewBindings。它将随Android Studio 3.6一起提供,并且如您所述,您使用的是Android Studio 3.4.2,因此无法正常工作。阅读this文章中的ViewBindings部分以获取更多参考。希望这会有所帮助!

答案 3 :(得分:1)

视图绑定仅在Android Studio 3.6 Canary 11+中可用。首先,您使用android gradle插件版本3.6.0-alpha11 +升级android studio(您现在可以同时使用beta,稳定版本尚未发布但可以使用beta),然后在build.gradle中添加以下代码

android {
        viewBinding.enabled = true
}

现在您可以像使用数据绑定那样使用

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"
}

就是这样。

答案 4 :(得分:0)

在您的班级文件中:

var binding = MainActivityBinding.inflate(layoutInflater) setContentView(MainActivity.this, R.layout.activity_Main)

binding.name = "Hello world"

在布局文件中: 父级布局将是<layout><data>

<?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"
    >
<!-- Inside the layout tag it is possible to set the data tag in order to set one or many variables. For this example we are having an User property-->
    <data>

        <variable
            name="name"
            type="String"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

<!-- your layout-->
     <TextView
        android:id="@+id/user_name_text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:text="@{name}" // here you can bind any data
        tools:text="Name"
        />

    </LinearLayout>

在Gradle中:

apply plugin: 'kotlin-android'                       
apply plugin: 'kotlin-kapt'
android {
    ....
    dataBinding {
        enabled = true
    }
}
dependencies {
    ...
    // notice that the compiler version must be the same than our gradle version
    kapt 'com.android.databinding:compiler:2.3.1'
}

答案 5 :(得分:0)

作为初学者,如果您想学习在您的 Android 项目中实现数据绑定

然后只需按照以下步骤操作:-

1:- 首先打开您的 Gradel Scripts 文件夹 并找到 build.gradel Module 文件并将此代码粘贴到 android 中 项目。

 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'
}

然后只需在您的 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">
    
<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:- 转到您的视图并为其分配一个 id:- android:id="@+id/textHere"

3:- 然后只需进入相应的 Activity 文件并在 Activity 类初始化下方放置

lateinit var 绑定:ActivityMainBinding;

注意 - ActivityMainBinding 这个词只是视图存在的文件与 + 'Binding' 的组合

例如:- 文件名:acvity_main.kt -------> ActivityMainBinding

在超级构造函数调用 put 下方的 onCreate 函数内

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

这里- R.layout.activity_main 是视图所在文件的名称

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!";
    }

}

现在您可以访问该视图的属性。

try binding.myId.text = "是的,它完成了!";

注意:- myId是我们在view中定义的id的名字

答案 6 :(得分:-1)

从Android Studio 3.6 canary11 +起,您可以使用ViewBinding。供参考,请参见this link