Android数据绑定

时间:2020-02-23 14:28:52  来源:igfitidea点击:

随着Android M的推出,一项值得注意的重大变化是Android数据绑定库的引入。
在本教程中,我们将研究它的需求并在我们的应用程序中实现它。

Android数据绑定概述

您有多少次看到活动/片段代码具有许多类似的行,这些行只是将代码与XML标记挂钩?一致地,这是开发人员要做的最无聊的工作。
此外,它还带来了一系列自身的问题,例如可读性问题,调试时间增加以及必须密切关注可能引起错误的烦人的样板代码。

多亏了ButterKnife库,我们能够使用注释来减少大量代码。
但这仍然需要我们使用@BindView或者@InjectView,并对每个视图手动逐个使用findViewById。

借助Android M引入DataBinding库是一种变相的祝福。
它使我们可以自由地最小化绑定到视图的应用逻辑代码。
DataBinding库提供了一种机制,该机制可以根据各自的视图ID在我们的代码中自动生成字段名称。
我们将尽快进行调查。
首先,让我们跳到集成方面。

Android数据绑定集成

要集成DataBinding,请确保gradle build bool版本为1.5或者更高版本

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

要启用数据绑定,请在应用程序模块的build.gradle中添加以下代码。

android {
  ...
  dataBinding {
      enabled = true
  }
}

同步Gradle使数据绑定可用于我们的项目。
让我们继续进行实施。

Android数据绑定项目结构

如下所示,我们将使用一个空的Android Studio项目进行实施。

布局

我们以前创建的较早的activity_main.xml布局如下所示:

<RelativeLayout android:layout_width="match_parent"
  android:layout_height="match_parent"

  android:paddingBottom="@dimen/activity_vertical_margin"
  android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
  android:paddingTop="@dimen/activity_vertical_margin"
  tools:context="com.theitroad.databinding.MainActivity"
  xmlns:tools="https://schemas.android.com/tools"
  xmlns:android="https://schemas.android.com/apk/res/android">

  <TextView
      android:id="@+id/tvHeading"
      android:layout_width="wrap_content"
      android:layout_centerHorizontal="true"
      android:layout_height="wrap_content"
      android:text="theitroad.local" 

  <TextView
      android:id="@+id/tvSubHeading"
      android:layout_width="wrap_content"
      android:layout_below="@+id/tvHeading"
      android:layout_centerHorizontal="true"
      android:layout_height="wrap_content"
      android:text="Android Tutorials" 
</RelativeLayout>

要使用数据绑定,我们需要添加一个布局作为根标签。

我们修改了activity_main.xml布局,使其包含" layout"标签,如下所示。

<layout xmlns:android="https://schemas.android.com/apk/res/android"
  xmlns:tools="https://schemas.android.com/tools">

<RelativeLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:paddingBottom="@dimen/activity_vertical_margin"
  android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
  android:paddingTop="@dimen/activity_vertical_margin"
  tools:context="com.theitroad.databinding.MainActivity">

  <TextView
      android:id="@+id/tvHeading"
      android:layout_width="wrap_content"
      android:layout_centerHorizontal="true"
      android:layout_height="wrap_content"
      android:text="theitroad.local" 

  <TextView
      android:id="@+id/tvSubHeading"
      android:layout_width="wrap_content"
      android:layout_below="@+id/tvHeading"
      android:layout_centerHorizontal="true"
      android:layout_height="wrap_content"
      android:text="Android Tutorials" 
</RelativeLayout>
</layout>

注意:您现在需要一次构建项目,以便在MainActivity.java中可以使用布局自动生成的字段名称。

代码

我们将默认的MainActivity.java替换为以下代码,以使用DataBinding。

package com.theitroad.databinding;

import android.databinding.DataBindingUtil;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.theitroad.databinding.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

  ActivityMainBinding binding;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

      binding.tvHeading.setText("Welcome to theitroad.local");
      binding.tvSubheading.setText("Welcome to this Android Tutorial on DataBinding");
  }
}

上面的代码中需要注意的新事物是:

  • ActivityMainBinding类是从xml布局文件生成的,因此命名方式是因为xml布局文件的名称已转换为Upper CamelCase并附加了Binding
  • 我们通过调用setContentView(这是一个静态方法)来调用xml布局
  • xml布局视图的ID也将转换为camelCase字段名称,如上面的代码所示。
    如您所见,现在更改TextView小部件的文本非常容易

注意:如果即使在构建项目后,ActivityMainBinding仍然不可用,请尝试重新启动Android Studio。
可能是因为缓存。

几个有趣的案例方案:

在当前的布局中,我们在camelCase中定义了ID。
如果您分配与android:id =" @ + id/tv_Heading"相同的ID,会发生什么?数据绑定也将其转换为camelCase,并且字段名称保持不变。

当两个ID分别为android:id =" @ + id/tvHeading"和android:id =" @ + id/tv_Heading"时,会发生什么情况?

理想情况下,DataBinding足够聪明,应该将android:id =" @ + id/tv_Heading"转换为tvHeading1字段名称。
但是没有保证。
同样,这可能导致在跟踪带有各自ID的字段名称时产生混乱。
因此,建议保留一种命名约定。
理想情况下为驼峰式。