DataBinding开发实践

一:概述

DataBinding 是谷歌Google发布的一个数据绑定框架,基于MVVM 模式,用于降低布局和逻辑的耦合性,使代码逻辑更加清晰(MVVM 相对于 MVP,其实就是将 Presenter 层替换成了 ViewModel 层)(但其IDE支持不完美,报错信息不直接,不支持重构)。但是最后要补充一句,使用DataBinding时,一定要注意命名的规范(我曾经因为忽略命名问题,导致调了一天的Bug,好惨,我好辣鸡)

  • 去掉Activity和Fragments的UI代码
  • XML变成UI的唯一来源
  • 不需要findViewById的步骤
  • 数据能够单向或双向绑定到 layout 文件中
  • 有助于防止内存泄漏
  • 自动进行空检测以避免空指针异常
  • 保证执行在主线程
  • MVVM:

二:添加DataBinding

1.Gradle的添加

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

2.在XML布局文件最外层套上<layout></layout>

<?xml version="1.0" encoding="utf-8"?>
<layout  xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.administrator.databindingtest.MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="test"/>

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="test"/>

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="test"/>

</LinearLayout>
</layout>

三.测试

关于命名规则:

  • 对于layout文件,首字母大写,去掉_改其后的首字母为大写,然后末尾添加Binding
  • 对于view的ID,类似于layout规则,但是首单词字母不大写
  • (注意:对于data class的引入,需要的是具有可观察性的data class:一种是实现Observable,第二种是实现LiveData(此相对于Observable更好用(个人认为,因为它能于DataBinding很好的结合)))
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /*setContentView(R.layout.activity_main);*/
        ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        binding.button.setText("测试点击");
        binding.textView.setText("测试textview");
    }

UI和事件的绑定:

数据的绑定:

在XML中添加数据

 <data>
        <variable
            name="employee"
            type="com.example.databindingtest.Employee"/>
        <!--type中添加了自定义的Employee的类-->
    </data>
<TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{employee.firstname}"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{employee.lastname}"/>

在MainActivity中调用:

 Employee employee = new Employee("shazi", "haha");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /*setContentView(R.layout.activity_main);*/
        ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        /*binding.button.setText("测试点击");
        binding.tVFirst.setText("测试textview");*/
        binding.setEmployee(employee);
    }

事件的绑定:(方法引用和监听器绑定两种方法)

方法引用:

先定义一个内部类class:

public class Presenter {
        public void onTextPresenter(CharSequence s, int start, int before, int count){
            employee.setFirstname(s.toString());
            employee.setLastname(s + "woshilastname");
            binding.setEmployee(employee);
        }

        public void onClick(View view){
            Toast.makeText(MainActivity.this, "点击了此组件!!!", Toast.LENGTH_SHORT).show();
        }
    }

重复之前的步骤:

​
<variable
            name="presenter"
            type="com.example.databindingtest.MainActivity.Presenter" />

​
 <EditText
            android:textSize="25dp"
            android:id="@+id/editText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="test"
            android:onTextChanged="@{presenter.onTextPresenter}"/>

<Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="test"
            android:onClick="@{presenter.onClick}"/>
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /*setContentView(R.layout.activity_main);*/
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        /*binding.button.setText("测试点击");
        binding.tVFirst.setText("测试textview");*/
        binding.setEmployee(employee);
        binding.setPresenter(new Presenter());
    }

监听器绑定:

在Presenter类中添加:

public void onClickListenerBinding(Employee employee){
            Toast.makeText(MainActivity.this, employee.getFirstname()
                    + "   " + employee.getLastname(), Toast.LENGTH_SHORT).show();
        }
<Button
            android:id="@+id/button_2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="事件监听器"
            android:onClick="@{() -> presenter.onClickListenerBinding(employee)}"/>

相对来说,监听器绑定灵活性更高,但是二者兼有所长,所以对于不同场合使用不同的绑定方法。

双向绑定:

DataBinding当ViewMoel层发生变化时,可以通过以上方法进行对View的自动更新。但是者仅仅时单项绑定,对于可输入(写)View(eg:EditText等),View更新之后却无法自动同步到ViewModel层。如果让ViewModel层持有View层的引用也可完成数据的同步。但是双向绑定的优点在于当View层数据更新之后,自动更新ViewModel层的数据,无需ViewModel持有View的引用,进一步解耦。

实现方法:@={表达式}

注意:当使用双向绑定时,涉及到绑定的变量对于其可见性有要求,只能是public(我曾经因为使用private而导致双向绑定失败,在overflow上得到解答,但是不知道有没有其他的解决方法,望大家知道的可以分享)

四:原理的认识

  • android.binding

流程:开始编译--》处理layout文件--》解析表达式--》java编译--》依赖解析--》找到setter

  • BR
  • xxxBinding

其他详细信息可以查看官网guides(Data Binding Library

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值