Android(安卓)DataBinding的简单使用
官方文档地址: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的布局文件上的,但实际上有时候我们需要动态地往布局添加一些组件,这个时候又怎么处理呢?或许只是我对它的了解还不够深吧,但目前它给我的感觉是比较难运用到实际业务当中去。
更多相关文章
- Android中使用PULL方式解析XML文件深入介绍
- Android(安卓)技术专题系列之五 -- 本地化
- android 打开预览不同类型文件
- android工程字符串多语言翻译遗漏查找工具
- Android(安卓)studio出现Error:Unable to tunnel through proxy.
- android模拟器SD卡使用
- Android(安卓)NDK移植libiconv和libxml2
- android 项目串口通信(serialPort)开发遇到的炕
- NPM 和webpack 的基础使用