Android DataBinding库(MVVM设计模式)

什么是MVVM

说到DataBinding,就有必要先提起MVVM设计模式。
Model–View–ViewModel(MVVM) 是一个软件架构设计模式,相比MVVM,大家对MVC或MVP可能会更加熟悉。

MVC:(VIew-Model-Controller)
早期将VIew、Model、Controller代码块进行划分,使得程序大部分分离,降低耦合。

1 MVP:(VIew-Model-Presenter)由于MVC中View和Model之间的依赖太强,导致Activity中的代码过于臃肿。为了他们可以绝对独立的存在,慢慢演化出了MVP。在MVP中View并不直接使用Model,它们之间的通信是通过 Presenter (MVC中的Controller)来进行的。

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

Data Binding

  1. 在Google I/O 2015上,伴随着Android M预览版发布的Data Binding兼容函数库。
    不知道要扯什么了,还是直接上代码,来看看Data Binding的魅力吧。
  2. Data Binding对使用的环境还是有一定要求的(这货有点挑)
    Android Studio版本在1.3以上
    gradle的版本要在1.5.0-alpha1以上
    需要在Android SDK manager中下载Android Support repository
    然后在对应的Module的build.gradle中添加
android {
      ....
      dataBinding {
          enabled =true
      }
    }
创建一个User类
public class User {
  private String firstName;
  private String lastName;

  public User(String firstName, String lastName) {
      this.firstName = firstName;
      this.lastName = lastName;
  }

  public String getFirstName() {
      return this.firstName;
  }

  public String getLastName() {
      return this.lastName;
  }

  public void setLastName(String lastName) {
      this.lastName = lastName;
  }

  public void setFirstName(String firstName) {
      this.firstName = firstName;
  }
}
在activity_main.xml中布局
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
  <data>
      <import type="com.example.gavin.databindingtest.User"/>
      <variable
          name="user"
          type="User" />
  </data>
  <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical"
      android:gravity="center"
      >
      <TextView
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@{user.firstName}"
          android:textSize="20sp" />
      <Button
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@{user.lastName}"
          android:textSize="25sp" />
  </LinearLayout>
</layout>
这里跟平时的布局有点不同,最外层是layout,里面分别是是data以及我们的布局。

data:声明了需要用到的user对象,type用于是定路径。
可以在TextView中的看到android:text="@{user.firstName}", 这是什么鬼,没见过这么写的!!!
(不急,继续往下看)

绑定数据

public class MainActivity extends AppCompatActivity {
  private ActivityMainBinding binding;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
      User user = new User("Micheal", "Jack");
      binding.setUser(user);
  }
}
问我ActivityMainBinding哪来的?我怎么知道…

ActivityMainBinding是根据布局文件的名字生成的,在后面加了Binding。

工作原理:

原来Data Binding 在程序代码正在编译的时候,找到所有它需要的信息。然后通过语法来解析这些表达式,最后生成一个类。
通过反编译我们可以看到,Data Binding为我们生成了databinding包,以及ActivityMainBinding类

这里写图片描述

看看我们在onCreate中最后调用的binding.setUser(user),在ActivityMainBinding中可以看到这个方法。

这里写图片描述

我想就是这个 super.requestRebind()对数据进行了绑定,至于里面怎么实现的,有待进一步研究。

上面只是用一个简单的例子,展示了Data Binding的用法,如果想在实际项目中使用,可不是上面这例子可以搞定的。下面就来说说Data Bindig的更多用法。

首先消除下大家对空指针的顾虑

自动生成的 DataBinding 代码会检查null,避免出现NullPointerException。
例如在表达式中@{user.phone}如果user == null 那么会为user.phone设置默认值null而不会导致程序崩溃(基本类型将赋予默认值如int为0,引用类型都会赋值null)

自定义DataBinding名

如果不喜欢自动生成的Data Binding名,我们可以自己来定义
<data class="MainBinding">
  ....
</data>
class对应的就是生成的Data Binding名
导包

跟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>

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
遇到相同的类名的时候:


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


使用alias设置别名,这样user对应的就是

com.example.gavin.databindingtest.User,mcUser就对应com.example.gavin.mc.User,然后

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}"/>


-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
当需要用到一些包时,在Java中可以自动导包,不过在布局文件中就没有这么方便了。需要使用import导入这些包,才能使用。如,需要用到View的时候


<data>
  <import type="android.view.View"/>
</data>
...
<TextView
...
android:visibility="@{user.isStudent ? View.VISIBLE : View.GONE}"
/>


注意:只要是在Java中需要导入包的类,这边都需要导入,如:Map、ArrayList等,不过java.lang包里的类是可以不用导包的


表达式

在布局中,不仅可以使用

android:text="@{user.lastName}"
还可以使用表达式如:

三元运算

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

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{user.isStudent? "Student": "Other"}'
android:textSize="30sp"/>

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

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="学生"
android:visibility="@{user.isStudent ? View.VISIBLE : View.GONE}"
android:textSize="30sp"/>
这里用到的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
三元运算符 ? :

显示图片

除了文字的设置,网络图片的显示也是我们常用的。来看看Data Binding是怎么实现图片的加载的。
首先要提到BindingAdapter注解,这里创建了一个类,里面有显示图片的方法。

public class ImageUtil {
  /**
   * 使用ImageLoader显示图片
   * @param imageView
   * @param url
   */
  @BindingAdapter({"bind:image"})
  public static void imageLoader(ImageView imageView, String url) {
      ImageLoader.getInstance().displayImage(url, imageView);
  }
}
(这方法必须是public static的,否则会报错)
这里只用了bind声明了一个image自定义属性,等下在布局中会用到。
这个类中只有一个静态方法imageLoader,里面有两参数,一个是需要设置图片的view,另一个是对应的Url,这里使用了ImageLoader库加载图片。
看看吧它的布局是什么样的吧

<?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"/>
  </data>

  <LinearLayout

      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical"
      android:gravity="center"
      >
      <ImageView
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          app:image = "@{imageUrl}"/>
  </LinearLayout>
</layout>
最后在MainActivity中绑定下数据就可以了

binding.setImageUrl(
  "http://115.159.198.162:3000/posts/57355a92d9ca741017a28375/1467250338739.jpg");
哇靠!!!就这样?我都没看出来它是怎么设置这些图片的。
不管了,先看看效果。(其中的原理以后慢慢唠,这里就负责说明怎么使用,这篇已经够长了,不想再写了)
引用:http://www.cnblogs.com/longjunhao/p/5860353.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值