码迷,mamicode.com
首页 > 移动开发 > 详细

Android MVP模式学习(二)----Data Binding结合

时间:2016-04-29 16:12:14      阅读:485      评论:0      收藏:0      [点我收藏+]

标签:

公司项目最近已经用MVP模式重新构造完成,重构后的项目直观明了,代码复用性高,易于调试维护。

之后主管让我去了解MVC,MVP ,MVVM,Data Binding相关的知识,于是便有了下面这篇博客。参考资料:
选择恐惧症的福音!教你认清MVC,MVP和MVVM

完全掌握Android Data Binding
这里很感谢这两篇文章的理论与技术支持,感谢这些大神。

OK,开始今天的主题。
关于MVP模式与MVVM模式孰是孰非,我想不是我一个初学者短短几句就能够说清楚的,我们也不用纠结于此。引用大神的话“真正的最佳实践都是人想出来的”。我们为何不结合一下MVP和MVVM的特点:MVP+Data Binding,依旧使用presenter去做和model层的通信,同时使用data binding去轻松的bind data。

Data Binding—-2015年的Google IO 大会上,Android 团队发布的一个 数据绑定框架。以后可以直接在 layout 布局 xml 文件中绑定数据,无需再通过findViewById或者注解框架去设置数据。

具体看看MVP+Data Binding在项目中的应用:
技术分享
点击button,请求加载网络数据,两秒过后,将模拟的数据显示在textView中。

1.准备工作
新建一个 Project,确保 Android 的 Gradle 插件版本不低于 1.5.0-alpha1:

classpath ‘com.android.tools.build:gradle:1.5.0‘

然后修改对应模块(Module)的 build.gradle:

dataBinding {
    enabled true
}

2.数据对象
这里的数据对象有两种情况,一种是普通的数据对象,一种是绑定的数据对象,能够自动更新数据。

先看第一种:

/**
 * Created by tangyangkai on 16/4/27.
 */
public class User{
    private String firstName;
    private String lastName;


    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

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

一个简单的User,两个属性以及它的 getter 和 setter。

3.布局文件

<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <variable
            name="user"
            type="com.example.tangyangkai.myapplication.User"></variable>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="getWebMsg"
            android:text="模拟请求网络数据" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="姓氏:" />

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

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="名字:" />

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

(1.)data节点:使用 Data Binding 之后,xml 的布局文件就不再用于单纯地展示 UI 元素,还需要定义 UI 元素用到的变量。所以,它的根节点不再是一个 ViewGroup,而是变成了 layout,并且新增了一个节点 data。data 节点的作用就像一个桥梁, 把数据(Model)与 UI(View) 进行绑定,搭建了 View 和 Model 之间的通路。
(2.)申明variable:

<data>
<variable
      name="user"
      type="com.example.tangyangkai.myapplication.User">            </variable>
</data>

在 xml 布局文件的 data 节点中声明一个 variable,这个变量会为 UI 元素提供数据(例如 TextView 的 android:text),然后在 Java 代码中把『后台』获取的数据与这个 variable 进行绑定。其中 type 属性就是我们在 Java 文件中定义的 User 类。
(3.)使用variable:

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

数据与 Variable 绑定之后,xml 的 UI 元素就可以直接使用了。

4.Activity实现

public class FiveActivity extends AppCompatActivity implements StringView {

    private StringPresenter mStringPresenter;
    ActivityFiveBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mStringPresenter = new StringPresenter(this);
        binding = DataBindingUtil.setContentView(
                this, R.layout.activity_five);

    }


    //请求网络数据
    public void getWebMsg(View view) {
        mStringPresenter.SetUrl();
    }

    @Override
    public void ShowString(String firstName, String lastName) {
        User user = new User();
        user.setFirstName(firstName);
        user.setLastName(lastName);
        binding.setUser(user);

    }
}

(1.)ActivityFiveBinding是框架自动生成的, 其中的set 方法也是根据 variable 名称而生成的。
(2.)修改 FiveActivity 的 onCreate 方法,用 DatabindingUtil.setContentView() 来替换掉 setContentView()
(3.)创建一个 User 对象,将从网络获取的数据通过set方法传递给User,通过 binding.setUser(user) 与 variable 进行绑定。

至此,使用第一种数据对象的data binding流程已经过了一遍,其实核心就是申明variable,绑定variable,使用variable。第二种数据对象也一样,只不过是绑定variable时候有些不一样。

5.第二种数据类型

/**
 * Created by tangyangkai on 16/4/27.
 */
public class User extends BaseObservable{
    private String firstName;
    private String lastName;

    @Bindable
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
        notifyPropertyChanged(BR.firstName);
    }

    @Bindable
    public String getLastName() {
        return lastName;
    }

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

(1.)要实现 数据对象的绑定,Android 原生提供了已经封装好的一个类 - -BaseObservable,并且实现了监听器的注册机制,我们只需要继承 BaseObservable。
(2.)BR 是编译阶段生成的一个类,功能与 R.java 类似,用 @Bindable 标记过 getter 方法会在 BR 中自动生成一个 entry。
(3.)当数据发生变化时会调用 notifyPropertyChanged(BR.firstName) 方法,通知系统 BR.firstName 这个 entry 的数据已经发生变化,再去更新 UI。

public class FiveActivity extends AppCompatActivity implements StringView {

    private StringPresenter mStringPresenter;
    User user = new User();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mStringPresenter = new StringPresenter(this);
        ActivityFiveBinding binding = DataBindingUtil.setContentView(
                this, R.layout.activity_five);
        binding.setUser(user);

    }


    //请求网络数据
    public void getWebMsg(View view) {
        mStringPresenter.SetUrl();
    }

    @Override
    public void ShowString(String firstName, String lastName) {
        user.setFirstName(firstName);
        user.setLastName(lastName);
    }
}

与第一种数据对象不同的是,variable的数据绑定会在初始化的时候就完成。获取网络数据成功以后,只要直接传递给user即可,数据以及UI的更新会在内部进行。

6.MVP的代码

Presenter层

/**
 * Created by tangyangkai on 16/4/11.
 * Presenter作为中间层,持有View和Model的引用,对model层的数据进行处理,控制View层的展示
 */
public class StringPresenter implements StringModel.getMsgListener {
    private StringView stringview;
    private StringModel stringmodel;


    public StringPresenter(StringView stringview) {
        this.stringview = stringview;
        stringmodel = new StringModel();
    }

    //对view层提供请求数据方法
    public void SetUrl() {
        stringmodel.getWebMsg(this);
    }

    //将model层返回的数据传递给view
    @Override
    public void getMsgSuccess(String firstName, String lastName) {
        stringview.ShowString(firstName, lastName);
    }
}

Model层


/**
 * Created by tangyangkai on 16/4/11.
 * 模拟请求数据,具体实战根据返回结果处理
 */
public class StringModel {

    public interface getMsgListener {
        void getMsgSuccess(String firstName, String lastName);
    }

    public void getWebMsg(getMsgListener listener) {
        //模拟网络数据请求
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        listener.getMsgSuccess("tang", "yangkai");
    }

}

之前一篇博客关于MVP的使用说的很清楚,这里就不详细解释了。
Android MVP模式学习(一)—-认知与使用

关于Data Binding的高级用法以及注意事项,开始那两篇文章介绍的很详细,大家可以细细品尝。

关于这些模式与框架,仁者见仁,智者见智,其实都是为了尽量降低程序的耦合性和提高代码的复用性。以上是记录自己最近学习这些框架模式的一些心得,有不当之处欢迎大家指出,一起进步。

公司开新项目了,准备投入新的战斗O(∩_∩)O~

Android MVP模式学习(二)----Data Binding结合

标签:

原文地址:http://blog.csdn.net/tyk0910/article/details/51263159

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!