DataBinding初识

来源:互联网 发布:linux 端口扫描工具 编辑:程序博客网 时间:2024/06/05 17:16

 DataBinding-MVVM设计模式:

       MVVM可以算是MVP的升级版,将 Presenter 改名为 ViewModel。关键在于 View和Model的双向绑定,当 View 有用户输入后,ViewModel通知 Model 更新数据,同理 Model 数据更新后,ViewModel通知 View 更新。

一  环境要求:

  • Android Studio 版本在1.3以上

  • Gradle 的版本要在1.5.0-alpha1 以上

  • 需要在 Android SDK manager 中下载Android Support repository


然后在对应的 Module build.gradle 中添加:


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

二 Databinding 当简单使用
(1)创建对象
public class User extends BaseObservable {    private String name;    private boolean isAdult;   @Bindable    public String getName() {        return name;    }    public void setName(String name) {              this.name = name;    }    @Bindable    public boolean isAdult() {        return isAdult;    }    public void setAdult(boolean adult) {               isAdult = adult;    } }

 创建好对象之后 接下来 就是在xml 设置进去啦

(1)建立xml
<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android"     >    <data>          <variable            name="user"            type="com.example.willer.databindingdemo.data.User"></variable>           </data><LinearLayout    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent">    <TextView        android:id="@+id/tv_name"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="@{user.name}"        />  </LinearLayout></layout>

需要值得注意的是,根节点以 layout 定义 而且是不需要设置宽高 属性当哦,节点data 可以认为是数据来源,通过代码中直接设置,简简单单当做完以上两步之后,就可以在代码中使用啦

(3)代码中使用

public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);        final User user = new User();        user.setName("willer");        user.setAdult(true);           binding.setUser(user);    }

经过简单三步之后,最简单的databinding使用就已经完成了,是不是很简单呢。 接下来我想说明一些在第一次使用dataBinding中的坑,在刚开使用的时候,始终疑惑,为什么我的代码生成不出 ActivityMainBinding  这个类,即这行代码

        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
后来去stackOverflow上查找了一下问题,最后只需要clean project 才生成,希望能帮助遇坑当小伙伴们,这仅仅是遇见当坑之一,稍微说明其他当一些坑。需要说明一下,ActivityMainBinding是自动生成当。

(3)设置点击事件


创建一个对象

public class MyHandlers {    public void onClickFriend(View view) { ... }}
<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android">   <data>       <variable name="handlers" type="com.example.Handlers"/>       <variable name="user" type="com.example.User"/>   </data>   <LinearLayout       android:orientation="vertical"       android:layout_width="match_parent"       android:layout_height="match_parent">       <TextView android:layout_width="wrap_content"           android:layout_height="wrap_content"           android:text="@{user.name}"           android:onClick="@{handlers::onClickFriend}"/>   </LinearLayout></layout>
另外一种用法

public class Presenter {    public void onSaveClick(Task task){}}
  <?xml version="1.0" encoding="utf-8"?>  <layout xmlns:android="http://schemas.android.com/apk/res/android">      <data>          <variable name="task" type="com.android.example.Task" />          <variable name="presenter" type="com.android.example.Presenter" />      </data>      <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent">          <Button android:layout_width="wrap_content" android:layout_height="wrap_content"          android:onClick="@{() -> presenter.onSaveClick(task)}" />      </LinearLayout>  </layout>

(4)消除空指针

自动生成的 DataBinding 代码会检查 null,避免出现NullPointerException

例如在表达式中 @{user.phone}如果user == null 那么会为 user.phone设置 默认值null而不会导致程序崩溃(基本类型将赋予默认值如 int为0,引用类型都会赋值null)。

(5)导包

跟Java中的用法相似,布局文件中支持 import 的使用,原来的代码是这样:


<data>    <variable name="user" type="com.example.gavin.databindingtest.User" />
</
data>


使用 import 后可以写成这样:


<data>    <import type="com.example.gavin.databindingtest.User"/>    <variable        name="user"        type="User" />
</
data>


遇到 相同的类名 的时候:




使用 alias 设置别名,这样 user 对应的就是 com.example.gavin.databindingtest.UsermcUser就对应com.example.gavin.mc.User,然后:


<TextView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="@{user.firstName}"/>
(6)三元运算


User 中添加 boolean类型 isStudent属性,用来判断是否为学生:




注意:需要用到双引号的时候,外层的双引号改成单引号。


还可以这样用:



这里用到的 View 需要在 data 中声明:


<data>    <import type="android.view.View"/>
</data>


注意:android:visibility="@{user.isStudent ? View.VISIBLE : View.GONE}",可能会被标记成红色,不用管它编译会通过的。


??


除了常用的操作法,另外还提供了一个 null 的合并运算符号 ??,这是一个三目运算符的简便写法。


contact.lastName ?? contact.name


相当于:


contact.lastName != null ? contact.lastName : contact.name


所支持的操作符如下:


数学运算符 + - / * %
字符串拼接 +
逻辑运算 && ||
二进制运算 & | ^
一元运算符 + - ! ~
位运算符 >> >>> <<
比较运算符 == > < >= <=
instanceof
Grouping ()
文字 - character, String, numeric, null
类型转换 cast
方法调用 methods call
字段使用 field access
数组使用 [] Arrary access
三元运算符 ? :



(7) 图片当加载

除了文字的设置,网络图片的显示也是我们常用的。来看看 Data Binding 是怎么实现图片的加载的。

/** * 使用ImageLoader显示图片 * @param imageView * @param url */@BindingAdapter({"bind:imageUrl"})public static void imageLoader(ImageView imageView, String url) {    Glide.with(imageView.getContext()).load(url).into(imageView);}
需要值得注意当是 上面这个方法必须是静态当 否则会报错

首先要提到 BindingAdapter注解,这里创建了一个类,里面有显示图片的方法:

这里只用了 bind 声明了一个 imageUrl 自定义属性,等下在布局中会用到。


这个类中只有一个静态方法 imageLoader,里面有两参数,一个是需要设置图片的 view,另一个是对应的 Url,这里使用了
Glide库加载图片。


看看它的布局是什么样的吧:

<?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"    >    <data>   <variable name="imageUrl"type="String"></variable>    </data><LinearLayout    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent">      <ImageView          app:imageUrl="@{imageUrl}"          android:layout_width="wrap_content"          android:layout_height="wrap_content" /></LinearLayout></layout>
注意哦,app这个属性不要忘记导入
    xmlns:app="http://schemas.android.com/apk/res-auto"

最后在 MainActivity 中绑定下数据就可以了:binding.setImageUrl("url");

是不是很方便,不用关心他是什么时候调用imageLoader这个静态方法,databinding直接会内部调用

(7)数据的绑定

a)Observable 对象

实现android.databinding.Observable接口的类可以允许附加一个监听器到Bound对象以便监听对象上的所有属性的变化。

Observable接口有一个机制来添加和删除监听器,但通知与否由开发人员管理。为了使开发更容易,一个BaseObservable的基类为实现监听器注册机制而创建。Data实现类依然负责通知当属性改变时。这是通过指定一个Bindable注解给getter以及setter内通知来完成的。

private static class User extends BaseObservable {   private String firstName;   private String lastName;   @Bindable   public String getFirstName() {       return this.firstName;   }   @Bindable   public String getFirstName() {       return this.lastName;   }   public void setFirstName(String firstName) {       this.firstName = firstName;       notifyPropertyChanged(BR.firstName);   }   public void setLastName(String lastName) {       this.lastName = lastName;       notifyPropertyChanged(BR.lastName);   }}

在编译期间,Bindable注解在BR类文件中生成一个Entry。BR类文件会在模块包内生成。如果用于Data类的基类不能改变,Observable接口通过方便的PropertyChangeRegistry来实现用于储存和有效地通知监听器。

b)Observable 字段

一些小工作会涉及到创建Observable类,因此那些想要节省时间或者几乎没有几个属性的开发者可以使用ObservableFieldsObservableFields是自包含具有单个字段的observable对象。它有所有基本类型和一个是引用类型。要使用它需要在data对象中创建public final字段:

private static class User {   public final ObservableField<String> firstName =       new ObservableField<>();   public final ObservableField<String> lastName =       new ObservableField<>();   public final ObservableInt age = new ObservableInt();}

就是这样,要访问该值,使用set和get方法:

user.firstName.set("Google");int age = user.age.get();
c)Observable 集合

一些app使用更多的动态结构来保存数据。Observable集合允许键控访问这些data对象。ObservableArrayMap用于键是引用类型,如String

ObservableArrayMap<String, Object> user = new ObservableArrayMap<>();user.put("firstName", "Google");user.put("lastName", "Inc.");user.put("age", 17);

在layout文件中,通过String键可以访问map:

<data>    <import type="android.databinding.ObservableMap"/>    <variable name="user" type="ObservableMap<String, Object>"/></data><TextView   android:text='@{user["lastName"]}'   android:layout_width="wrap_content"   android:layout_height="wrap_content"/><TextView   android:text='@{String.valueOf(1 + (Integer)user["age"])}'   android:layout_width="wrap_content"   android:layout_height="wrap_content"/>

ObservableArrayList用于键是整数:

ObservableArrayList<Object> user = new ObservableArrayList<>();user.add("Google");user.add("Inc.");user.add(17);

在layout文件中,通过索引可以访问list:

<data>    <import type="android.databinding.ObservableList"/>    <import type="com.example.my.app.Fields"/>    <variable name="user" type="ObservableList<Object>"/></data><TextView   android:text='@{user[Fields.LAST_NAME]}'   android:layout_width="wrap_content"   android:layout_height="wrap_content"/><TextView   android:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}'   android:layout_width="wrap_content"   android:layout_height="wrap_content"/>

后续的内容 下次补充哈




















原创粉丝点击