Skip to content

使用databinding

通过databinding功能,您可以更轻松地编写可与视图交互的代码。在模块中启用databinding之后,系统会为该模块中的每个 XML 布局文件生成一个绑定类。绑定类的实例包含对在相应布局中具有 ID 的所有视图的直接引用。

在大多数情况下,databinding会替代 findViewById

启用databinding,需要在模块的gradle文件中添加

android {
    // ....
    dataBinding {
        enabled true
    }
}

在layout中,添加<layout>标签。例如act_data_binding_1.xml文件。 其中包含了data标签与view标签,view标签的内容就是不使用DataBinding时的普通布局内容

<?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:binding="http://schemas.android.com/tools">

    <!-- 根视图 -->
    <LinearLayout.... />

</layout>

系统会通过以下方式生成绑定类的名称:将 XML(layout)文件的名称转换为驼峰式大小写,并在末尾添加“Binding”一词。 上面的xml会生成ActDataBinding1Binding类。我们可以直接使用这个类。

DataBindingAct1中,也需要调用setContentView

public class DataBindingAct1 extends AbsActivity {

    ActDataBinding1Binding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActDataBinding1Binding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        binding.tv1.setText("现在可以直接使用layout中的TextView了");
        binding.tv2.setText("可以不用findViewById");
    }
}

可以看到,我们不用写那么多findViewById了。可以直接使用binding。 每个绑定类还包含一个getRoot()方法,用于为相应布局文件的根视图提供直接引用。在此示例中,ActDataBinding1Binding类中的 getRoot() 方法会返回 LinearLayout 根视图。

使用DataBindingUtil

前面在onCreate中使用了ActDataBinding1Binding.inflate(getLayoutInflater()), 我们也可以换用DataBindingUtil.setContentView

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

binding 与 findViewById 的区别

与使用 findViewById 相比,视图绑定具有一些很显著的优点: * Null 安全:由于视图绑定会创建对视图的直接引用,因此不存在因视图 ID 无效而引发 Null 指针异常的风险。此外,如果视图仅出现在布局的某些配置中,则绑定类中包含其引用的字段会使用 @Nullable 标记。 * 类型安全:每个绑定类中的字段均具有与它们在 XML 文件中引用的视图相匹配的类型。这意味着不存在发生类转换异常的风险。

这些差异意味着布局和代码之间的不兼容性可能会导致编译版本在编译时(而非运行时)失败。

基础Activity示例

我们设计一个抽象类BaseAct封装一些常用操作,它指定了继承自ViewDataBinding的范型。

/**
 * activity 抽象类
 */
public abstract class BaseAct<B extends ViewDataBinding> extends AppCompatActivity {

    protected B binding;

    /**
     * @return 界面对应的layout id
     */
    protected abstract int getLayoutId();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, getLayoutId());
    }
}

实现类继承BaseAct,指定ViewDataBinding的子类后,直接可以使用binding对象了。

public class MainActivity extends BaseAct<ActMainBinding> {

    @Override
    protected int getLayoutId() {
        return R.layout.act_main;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 具体操作
    }

    @Override
    public void onBackPressed() {

    }
}