2015年谷歌I/O大会上介绍了一个框架DataBinding,DataBinding是一个数据绑定框架,以前我们在Activity里写很多的findViewById,现在如果我们使用DataBinding,就可以抛弃findViewById。DataBinding主要解决了两个问题: - 需要多次使用findViewById,损害了应用性能且令人厌烦 - 更新UI数据需切换至UI线程,将数据分解映射到各个view比较麻烦
就让我们具体来看看怎么使用它吧。
[注意]:我介绍是基于android stadio1.5及以上开发工具
在应用的build.gradle文件中添加如下代码:
android { ... //导入dataBinding支持 dataBinding{ enabled true } ... }布局文件
<!--布局以layout作为根布局--> <layout> <!--我们需要展示的布局--> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="www.zhang.com.databinding.MainActivity"> <Button android:id="@+id/main_tv1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="单纯的摆脱findviewbyid" /> </LinearLayout> </layout>布局通过DataBindingUtils.setContentView()加载到代码中,而且会生成对应一个Binding对象,对象名是布局文件文称加上Binding后缀
MainActivity中代码
public class MainActivity extends AppCompatActivity { private ActivityMainBinding binding;//这个类是自动生成的 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //通过DataBInding加载布局都会对应的生成Binding对象,如ActivityMainBinding,对象名在布局文件名称后加上了一个后缀Binding binding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main); //通过binfding.id名称---就相当于获取了改控件对象了 binding.mainTv1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { binding.mainTv1.setText("没有findviewbyid了"); } }); } }通过Binding对象.id名称,就相当于拿到了指定的布局中的id的控件了,使用起来和findviewbyid获取的控件是一样的
布局文件
<?xml version="1.0" encoding="utf-8"?><!--布局以layout作为根布局--> <layout> <data> <!--绑定基本数据类型及String--> <!--name: 和java代码中的对象是类似的,名字自定义--> <!--type: 和java代码中的类型是一致的--> <variable name="content" type="String" /> <variable name="enabled" type="boolean" /> </data> <!--我们需要展示的布局--> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <!--绑定基本数据类型及String的使用是通过 @{数据类型的对象} 通过对应数据类型的控制显示--> <Button android:id="@+id/main_tv2" android:layout_width="match_parent" android:layout_height="wrap_content" android:clickable="@{enabled}" android:text="@{content}" /> </LinearLayout> </layout>在布局中是通过@{}来绑定数据的,{}中是布局中该控件属性对应的数据类型数据,同时还可以支持运算符运算和静态方法调用和转换,这个后面会介绍
MainActivity文件中
public class MainActivity extends AppCompatActivity { private ActivityMainBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //通过DataBInding加载布局都会对应的生成一个对象,如ActivityMainBinding,对象名在布局文件名称后加上了一个后缀Binding binding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main); //2.绑定基本数据类型及String binding.setContent("对String类型数据的绑定");//setContent就是给布局文件text属性绑定的content设置值 binding.setEnabled(false);//设置enabled值为false //给控件设置点击事件,发现其实点击无效,因为在布局文件中给cilckable属性绑定了enabled,在代码中设置enabled值为false,所以点击事件无效 binding.mainTv2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "我被点击了", Toast.LENGTH_SHORT).show(); } }); } }Model数据类型
public class User { private String text; public User(String text) { this.text = text; } public String getText() { return text; } public void setText(String text) { this.text = text; } }后面会对model数据做更详细的讲解,这里先让大家知道一下用法
布局文件
<?xml version="1.0" encoding="utf-8"?><!--布局以layout作为根布局--> <layout> <data> <!--绑定Model数据2中形式,一中是导入该类型的,一种指定类型的全称,和java一样--> <!-- 方式一 --> <variable name="user" type="www.zhang.com.databinding.User" /> <!-- 方式二 --> <!--<import type="www.zhang.com.databinding.User" />--> <!--<variable--> <!--name="user"--> <!--type="User" />--> </data> <!--我们需要展示的布局--> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/main_btn3" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@{user.text}" /><!--这里user.text相当于user.getText()--> </LinearLayout> </layout>MainActivity
public class MainActivity extends AppCompatActivity { private ActivityMainBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //通过DataBInding加载布局都会对应的生成一个对象,如ActivityMainBinding,对象名在布局文件名称后加上了一个后缀Binding binding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main); //3.绑定model对象数据 User user = new User("绑定Model数据类型"); binding.setUser(user);//或者 binding.setVariable(BR.user,user); } }binding设置数据有2中方式:1.binding.setUser(user) 2.binding.setVariable(BR.user,user)–采用BR指定
布局文件
<?xml version="1.0" encoding="utf-8"?><!--布局以layout作为根布局--> <layout> <data> <variable name="event" type="www.zhang.com.databinding.model.EventListener" /> <variable name="title1" type="String" /> <variable name="title2" type="String" /> <variable name="title3" type="String" /> <variable name="title4" type="String" /> </data> <!--我们需要展示的布局--> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="@{event.click1}" android:text="@{title1}" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="@{event::click2}" android:text="@{title2}" /> <!--android:onClick="@{event::click2}" 编译报错没关系,可以运行的--> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="@{()->event.cilck3(title4)}" android:text="@{title3}" /> </LinearLayout> </layout>事件有多种写法
1.android:onClick="@{event.click1}" 2.android:onClick="@{event::click2}" 3.android:onClick="@{()->event.cilck3(title4)}" [注]:()->event.cilck3(title4)是lambda表达式写法, 也可以写成:(view)->event.cilck3(title4),前面(view)表示onClick方法的传递的参数, 如果event.click3()方法中不需要用到view参数,可以将view省略。 当然event.click1也可以写成(view)->event.click1(view),将onClick(View view)的view参数传递给event.click1(view)方法。 大概就这意思,以下是伪代码 onclick(View view){ event.click1(view) }EventListener接口
public interface EventListener{ public void click1(View v); public void click2(View v); public void cilck3(String s); }MainActivity
public class MainActivity extends AppCompatActivity{ private ActivityMainBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //通过DataBInding加载布局都会对应的生成一个对象,如ActivityMainBinding,对象名在布局文件名称后加上了一个后缀Binding binding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main); binding.setTitle1("事件绑定1"); binding.setTitle2("事件绑定2"); binding.setTitle3("事件绑定3"); binding.setTitle4("change ok"); binding.setEvent(new EventListener() { @Override public void click1(View v) { binding.setTitle1("事件1方法调用"); } @Override public void click2(View v) { binding.setTitle2("事件2方法调用"); } @Override public void cilck3(String s) { binding.setTitle3(s); } }); } }