<Android 基础(五)> MVVM

介绍

MVVM,Model-View-ViewModel,与上次讲的MVP模式比较的类似,MVP中需要大量的接口文件,而MVVM模式下,View和ViewModel直接关联,使用上比较方便,简化了代码,大致的结构图如下:

这里写图片描述

可以看待View和ViewModel是双向的交互,这一点很关键

DataBinding

Data Binding Library是Google推出的,可以说是针对MVVM模式的支持库,通过在Layout中进行数据的访问,来实现View和Data的双向绑定。不仅使用灵活,用法丰富,而且支持也是相当的广泛,很大程度上降低了代码量和耦合性,减少了开发者的压力。

build.gradle

    dataBinding {
        enabled= true
    }

这样使用比较的方法,当然这个需要当前的Gradle版本支持这个属性

Layout Data

<?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"
    xmlns:tools="http://schemas.android.com/tools">
    <data>
        <import type="com.example.mraz.mvvmdemo.Model.User"></import>
        <variable
            name="user"
            type="User">
        </variable>
    </data>
    <LinearLayout ...
    </LinearLayout>
</layout>

最完成使用Layout属性,通过data属性值,添加需要在布局文件中使用的变量和对应的变量类型,也可以先import文件,然后直接使用,不然就需要在type中使用类型的完整路径,当遇到相同的类名的时候,DataBinding支持别名的定义,alias

Layout Access Data

布局文件文件中如何实现对绑定数据的访问

                <TextView
                    android:id="@+id/tv_username"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@{user.getUsername()}" />

                <TextView
                    android:id="@+id/tv_password"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@{user.getPassword()}" />

使用格式为“@{ }”,大括号中的使用方式与代码中的基本无差别,可以使用方法,也可以使用对应的成员变量,当然如果权限允许的话,如果要直接访问private变量或者方法,显然是不现实的。

Activity Set Data

public class MainActivity extends AppCompatActivity {
    User user = new User("", "");
    @Bind(R.id.et_username)
    EditText etUsername;
    @Bind(R.id.et_password)
    EditText etPassword;
    @Bind(R.id.tv_username)
    TextView tvUsername;
    @Bind(R.id.tv_password)
    TextView tvPassword;

    ActivityMainBinding activityMainBinding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        ButterKnife.bind(this);
}

    @OnTextChanged(value = R.id.et_username, callback = OnTextChanged.Callback.TEXT_CHANGED)
    void onUserNameChanged(CharSequence s,int start,int before,int count) {
        user.setUsername(s.toString());
        activityMainBinding.setUser(user);
    }

    @OnTextChanged(value = R.id.et_password, callback = OnTextChanged.Callback.TEXT_CHANGED)
    void onPasswordChangedps(CharSequence s,int start,int before,int count) {
        user.setPassword(s.toString());
        activityMainBinding.setUser(user);
    }

}

几个关键点:
1. ActivityMainBinding activityMainBinding
这里定义的变量类型ActivityMainBinding 与布局文件对应
activity_main ——-> ActivityMainBinding
first_second ——-> FirstSecondingBinding

Binding类的命名是基于所述layout文件的名称,用大写开头,除去下划线()以及()后的第一个字母大写,然后添加“Binding”后缀。这个类将被放置在一个模块封装包里的databinding封装包下
Binding类可通过调整data元素中的class属性来重命名或放置在不同的包中。例如:

<data class="UserBinding">
    ...
</data>

2.activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
获取ActivityMainBinding对象,用于后面设置变量
3. activityMainBinding.setUser(user);
设置数据,User变量

表达式
常用的表达式和正常的java代码比较类似
- 数学 + - / * %
- 字符串连接 +
- 逻辑 && ||
- 二进制 & | ^
- 一元运算 + - ! ~
- 移位 >> >>> <<
- 比较 == > < >= <=
- instanceof
- 分组 ()
- null
- Cast
- 方法调用
- 数据访问 []
- 三元运算 ?:

不支持的操作:
this
super
new
显式泛型调用

实际效果图

这里写图片描述

备注:
关于DataBinding,这里有一篇文章讲得很清晰,推荐一下
https://segmentfault.com/a/1190000002876984

效果图对应的代码贴了一部分,实现相对比较容易,这里就不赘述了,如果有需要的留言,我再附上。

posted on 2016-06-05 11:37  岚之山  阅读(169)  评论(0编辑  收藏  举报

导航