欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MVVM使用简介

程序员文章站 2022-06-02 09:28:56
...

我们一步步来,从MVC开始。
MVC 我们都知道,模型——视图——控制器。为了使得程序的各个部分分离降低耦合性,我们对代码的结构进行了划分。
MVVM使用简介
            
    
    博客分类: android androidmvvm 
他们的通信方式也如上图所示,即View层触发操作通知到业务层完成逻辑处理,业务层完成业务逻辑之后通知Model层更新数据,数据更新完之后通知View层展现。在实际运用中人们发现View和Model之间的依赖还是太强,希望他们可以绝对独立的存在,慢慢的就演化出了MVP。
MVVM使用简介
            
    
    博客分类: android androidmvvm 
Presenter 替换掉了Controller,不仅仅处理逻辑部分。而且还控制着View的刷新,监听Model层的数据变化。这样隔离掉View和Model的关系后使得View层变的非常的薄,没有任何的逻辑部分又不用主动监听数据,被称之为“被动视图”。
MVVM使用简介
            
    
    博客分类: android androidmvvm 
至于MVVM基本上和MVP一模一样,感觉只是名字替换了一下。他的关键技术就是今天的主题(Data Binding)。View的变化可以自动的反应在ViewModel,ViewModel的数据变化也会自动反应到View上。这样开发者就不用处理接收事件和View更新的工作,框架已经帮你做好了。

Data Binding Library

今年的Google IO 大会上,Android 团队发布了一个数据绑定框架(Data Binding Library)。以后可以直接在 layout 布局 xml 文件中绑定数据了,无需再 findViewById 然后手工设置数据了。其语法和使用方式和 JSP 中的 EL 表达式非常类似。
下面就来介绍怎么使用Data Binding Library。

以上是应用网上的一些资料,就是简单介绍下

接下来上代码

首先配置环境,在gradle中

android{

dataBinding{
    enabled = true
}

}

dataBinding的布局文件和我平时写的有些不同,他的根节点是layout

来让我们看一下

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <import type="android.text.TextUtils" />

        <variable
name="myEvent"
type="com.example.wudz.mvvm.MVVMActivity.MyEvent" />

        <variable
name="user"
type="com.example.wudz.bean.UserBean" />
    </data>

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

        <RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">

            <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:layout_alignParentRight="true"
android:text="@{TextUtils.isEmpty(user.name)?null: user.name}" />
        </RelativeLayout>

        <RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">

            <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:layout_alignParentRight="true"
android:text="@{TextUtils.isEmpty(user.age)?null: user.age}" />
        </RelativeLayout>

        <Button
style="@style/btn"
android:onClick="@{myEvent.setInf}"
android:text="设置name和age" />

        <ListView
android:id="@+id/lv_user"
android:layout_width="match_parent"
android:layout_height="wrap_content"></ListView>
    </LinearLayout>
</layout>

里面包含data节点,data里面包含import节点和variable节点,其中variable节点中的name相当于我们在类里面的变量名(个人理解的),type相当于类型,只不过是全路径的,这点要注意,当然,如果是string、int等,就不用写完整路径了

android:text="@{user.name}是吧UserBean的name属性和TextView 的text属性绑定起来,

在布局里面可以使用多种表达式:

  • 数学表达式 + – / * %

  • 字符串链接 +

  • 逻辑操作符 && ||

  • 二元操作符 & | ^

  • 一元操作符 + – ! ~

  • Shift >> >>> <<

  • 比较 == > < >= <=

  • instanceof

  • Grouping ()

  • Literals – character, String, numeric, null

  • Cast

  • 函数调用

  • 值域引用(Field access)

  • 通过[]访问数组里面的对象

  • 三元操作符 ?:
    示例:

    android:text="@{String.valueOf(index + 1)}"
    android:visibility="@{age &lt; 13 ? View.GONE : View.VISIBLE}"
    android:transitionName='@{"image_" + id}'

可以参考:http://developer.android.com/tools/data-binding/guide.html#expression_language

 

看下userBean

package com.example.wudz.bean;

import android.databinding.BaseObservable;
import android.databinding.Bindable;

import java.io.Serializable;

/**
 * USER:wudz on 2016/11/2 09:57
 * <p>
* EMAIL:wudz@qianbaocard.com
 * <p>
* TODO
*/

public class UserBean extends BaseObservable implements Serializable {
    private String name;
    private String age;

    public void setName(String name) {
        this.name = name;
}
    @Bindable
public String getName() {
        return name;
}
    @Bindable
public String getAge() {
        return age;
}

    public void setAge(String age) {
        this.age = age;
}
}

让你的绑定数据类继承BaseObservable,然后通过调用notifyPropertyChanged方法来通知界面属性改变

在需要通知的属性的get方法上加上@Bindable,这样编译阶段会生成BR.[property name],然后使用这个调用方法notifyPropertyChanged就可以通知界面刷新了。如果你的数据绑定类不能继承BaseObservable,那你就只能自己实现Observable接口,可以参考BaseObservable的实现。

还可以这样做,我没写到demo中,在网上找的一段,大家参考下

方案二

Data Binding Library提供了很便利的类ObservableField,还有ObservableBoolean, ObservableByte, ObservableChar, ObservableShort, ObservableInt, ObservableLong, ObservableFloat, ObservableDouble, 和 ObservableParcelable,基本上涵盖了各种我们需要的类型。用法很简单,如下:

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

    public final ObservableField<String> lastName = new ObservableField<>();

    public final ObservableInt age = new ObservableInt();
}

然后使用下面的代码来访问:

user.firstName.set("Google");int age = user.age.get();

调用set方法时,Data Binding Library就会自动的帮我们通知界面刷新了。

在java代码中调用

package com.example.wudz.mvvm;

import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;

import com.example.wudz.bean.UserBean;
import com.example.wudz.mvvm.databinding.ActivityMvvmBinding;
import com.example.wudz.mvvm.databinding.ItemUserBinding;

import java.util.ArrayList;
import java.util.List;

/**
 * USER:wudz on 2016/11/2 09:54
 * <p>
* EMAIL:wudz@qianbaocard.com
 * <p>
* TODO
*/

public class MVVMActivity extends AppCompatActivity {
    //在这里会生成ViewDataBinding的形势的类,继承ViewDataBinding
private ActivityMvvmBinding binding;
    private ListView lvUser;
    private List<UserBean> list = new ArrayList<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this,R.layout.activity_mvvm);
binding.setMyEvent(new MyEvent());
lvUser = (ListView) binding.getRoot().findViewById(R.id.lv_user);
UserBean user = new UserBean();
user.setAge("20");
user.setName("小明");
list.add(user);
list.add(user);
list.add(user);
list.add(user);
list.add(user);
list.add(user);
list.add(user);
list.add(user);
lvUser.setAdapter(new MyAdapter());
}

    public class MyEvent{
        public void setInf(View view){
            UserBean user = new UserBean();
user.setAge("20");
user.setName("小明");
binding.setUser(user);
}
    }
    class MyAdapter extends BaseAdapter{
        ItemUserBinding itemUserBinding;
@Override
public int getCount() {
            return list.size();
}

        @Override
public Object getItem(int position) {
            return list.get(position);
}

        @Override
public long getItemId(int position) {
            return position;
}

        @Override
public View getView(int position, View convertView, ViewGroup parent) {
            if(convertView == null){
                itemUserBinding = DataBindingUtil.inflate(LayoutInflater.from(MVVMActivity.this),R.layout.item_user,parent,false);
convertView = itemUserBinding.getRoot();
convertView.setTag(itemUserBinding);
}else{
                itemUserBinding = (ItemUserBinding) convertView.getTag();
}
            itemUserBinding.setUser(list.get(position));
            return convertView;
}
    }
}

另外就是在adapter适配器中稍微有点不一样,

以前我们都是定义一个viewHolder什么的,在这里我们获取到itemUserBinding,把这个对象设置converView的tag中,这里类似viewholder了,在给item设置值得时候,直接itemUserBinding.setUser(list.get(position))

现在大多人都用RecycleView,这里只是给大家举个例子,

以上就是MVVM的简单介绍,欢迎补充

附上demo地址

https://github.com/wudongze/MVVM

 

相关标签: android mvvm