官方文档地址:https://developer.android.google.cn/topic/libraries/data-binding       

        先说说开发环境,本人使用的Android Studio 版本为3.5,gradle版本是5.4.1,在此之下的版本不确保能用。

        要使用DataBinding需要在项目对应的gradle文件中添加以下的设置

android {    ........    //介绍网址https://developer.android.google.cn/jetpack/androidx/releases/databinding    dataBinding {        enabled = true    }}dependencies {    implementation fileTree(dir: 'libs', include: ['*.jar'])    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'    testImplementation 'junit:junit:4.12'    androidTestImplementation 'androidx.test.ext:junit:1.1.1'    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'    implementation 'androidx.appcompat:appcompat:1.1.0'//包含大部分androidx的类}

        创建数据实体类User.java和类型转换工具类Converter.java,看不懂这两个类没关系,后面会用到,看完后面再回头看这两个类的作用。(ViewModel的介绍可以看我另外一篇文章Android ViewModel的使用)

import androidx.databinding.ObservableField;import androidx.lifecycle.ViewModel;public class User extends ViewModel {    public String name;    public int age;    public final ObservableField observableName = new ObservableField<>();//可观察的数据对象    public final ObservableField observableAge = new ObservableField<>();    public User(){        name = "name";        age = 18;        observableName.set("observableName");        observableAge.set(8);    }}
import android.util.Log;import androidx.databinding.InverseMethod;/** * 数据类型装换工具类 * 每种类型装换必须有两个方法相互对应 * 有@InverseMethod注解的是在布局文件中双向绑定时可以调用的方法 * 没有@InverseMethod注解的方法看起来没有用到,但实际在双向绑定时会被自动调用 */public class Converter {    @InverseMethod("stringToInt")//对应下面stringToInt方法    public static String intToString(int value) {        Log.d("JohnLiu","intToString:"+ value);        return  String.valueOf(value);    }    public static int stringToInt(String value) {        Log.d("JohnLiu","stringToInt:"+ value);        if (Long.valueOf(value) > Integer.MAX_VALUE){            throw new RuntimeException("数值超出");        }        return  Integer.valueOf(value);    }}

  Activity和layout文件如下(tips,如果遇到项目编译失败,检查一下Activity文件所在的文件目录是否符合规范,文件夹名称为小写。还有一种情况,通过File-》Invalidate Caches/Restart 清缓存并重启)。

import androidx.appcompat.app.AppCompatActivity;import androidx.databinding.DataBindingUtil;public class DataBindingActivity extends AppCompatActivity {    //系统会为每个布局文件生成一个绑定类。默认情况下,类名称基于布局文件的名称,它会转换为 Pascal 大小写形式并在末尾添加 Binding 后缀。    // 本Activity布局文件名为 activity_data_binding,因此生成的对应类为 ActivityDataBindingBinding    private ActivityDataBindingBinding mBinding;    private User user;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        user = new User();//等价于user = ViewModelUtils.getPrivateViewModel(this,User.class,this);//        user = ViewModelUtils.getViewModel(this,User.class);//全局唯一,即在app退出之前,下次重新进来这个页面会加载上一次的数据        //DataBindingUtil输入的时候AS有可能不会智能提示,需要手动导入一下androidx.databinding.DataBindingUtil        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_data_binding);        //根据绑定的layout中的variable标签里name设置的值变化,比如我设置的是data,这里方法就是setData,如果设置成user,这里就是setUser,如此类推        mBinding.setData(user);        findViewById(R.id.bt_set).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                //值变化,但屏幕没刷新,需要手动调用一次 mBinding.setData(user);                user.name="JohnLiu";                user.age =  20;                //只要值变化,数据就会同步显示到屏幕上                user.observableName.set("JohnLiu");                user.observableAge.set(20);            }        });        findViewById(R.id.bt_refresh).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                //调用一次 mBinding.setData(user);后可以看到前两行的值也刷新了                mBinding.setData(user);            }        });        findViewById(R.id.bt_toast).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                String msg = "name:" + user.name + "\n"                        + "age:" + user.age + "\n"                        + "observableName:" + user.observableName.get() + "\n"                        + "observableAge:" + user.observableAge.get();                //显示当前实体类中所有变量的值                Toast.makeText(DataBindingActivity.this,msg,Toast.LENGTH_SHORT).show();            }        });    }}

其中activity_data_binding.xml的内容如下

<?xml version="1.0" encoding="utf-8"?>                                                                                

刚启动的页面如下:

点击赋值&当前值,可以看到虽然实体类中的值变了,但是前两行文本没有同步刷新

                

点击刷新,可以看到前两行文本也刷新了,这就是用了可观察对象ObservableField与没用的区别。ObservableField会监听值的变化,实时刷新屏幕。

修改最后两行的文本,可以看到修改视图中的文本,同时会修改实体类中相应的可观察对象的值,实现数据双向绑定。是否实现双向绑定,区别在于 android:text="@={Converter.intToString(data.observableAge)}" 里面的“@”后面有无“=”,如果没有“=”,修改实体类中的值,会刷新视图,但修改视图,不会同时修改实体类的值。

 

小结

        从效果看来,使用DataBinding好像减少很多代码,大部分的取/赋值操作自动完成 ,不需要关注值的变化去更新视图。但实际业务大多数要对数据的格式或取值进行校验并做一些处理,并不仅仅只是把值赋给实体对象。还有,可以看到DataBinding的赋值逻辑是写在XML的布局文件上的,但实际上有时候我们需要动态地往布局添加一些组件,这个时候又怎么处理呢?或许只是我对它的了解还不够深吧,但目前它给我的感觉是比较难运用到实际业务当中去。

更多相关文章

  1. Android中使用PULL方式解析XML文件深入介绍
  2. Android(安卓)技术专题系列之五 -- 本地化
  3. android 打开预览不同类型文件
  4. android工程字符串多语言翻译遗漏查找工具
  5. Android(安卓)studio出现Error:Unable to tunnel through proxy.
  6. android模拟器SD卡使用
  7. Android(安卓)NDK移植libiconv和libxml2
  8. android 项目串口通信(serialPort)开发遇到的炕
  9. NPM 和webpack 的基础使用

随机推荐

  1. android的Material Design点击涟漪效果
  2. android ListView 显示在底部
  3. SDK下载地址
  4. android 图片处理
  5. Android(安卓)basic1
  6. Android7.0中文API -- SeekBar
  7. Android圆型头像实现
  8. 【Android】自定义 Tabhost
  9. Android(安卓)SystemClock
  10. Android(安卓)basic1