浅谈Android中MVC、MVP、MVVM模式(三)

三、MVVM的义军突起
    前面,在《浅谈Android中MVC、MVP、MVVM模式(一)》 浅谈Android中MVC、MVP、MVVM模式(二) 中我们学习了MVC和MVP,并分析了两者的差异,下面就让我们继续学习下MVVM。
    MVVM是Model-View-ViewModel的简写,MVVM框架的由来便是MVP模式与WPF结合的应用方 式时发展演变过来的一种新型架构框架。
    MVVM包含了三部分:
  • Model : 业务逻辑和实体模型
  • View :显示内容
  • ViewModel : 将前面两者联系在一起的对象(实现ViewModle,谷歌官方提供了一个工具,DataBinding)
Android Data Binding前言,
    2015年的I/O大会上谷歌介绍了一个非常牛逼的工具,该工具可以让你 将View和一个对象的field绑定。当field更新的时候,framework将收到通知,然后View自动更新。 Data Binding 官方原生支持MVVM模型可以让我们在不改变既有代码框架的前提下,非常容易的使用这些新特性。

MVVM 也是基于MVC上的一种演变, 它将Activity中的View给拆分出来了,再通过谷歌提供的DataBinding工具将View和Model关联到一起。
它可以用一个简单的模型图表示

与MVC、MVP 对比来看, MVVM看起来似乎更为简洁,思路更明确了。从代码上来看,主要是依赖于DataBinding工具的强大支持
下面, 还是让我们用一个模拟登陆的简单Demo来演示一下,
先看项目结构

OK, 接下来一步一步的编写思路。

(一)Model
实体类User 和业务类UserLoginHttp, 更MVC中的一样, 不再贴出代码了。
此处贴出另一种实体User类的写法, 便于  将View和一个对象的field绑定 ,具体请参考Google的官方文档
//Model 实体
public class User {
public final ObservableField<String> username = new ObservableField<>();
public final ObservableField<String> password = new ObservableField<>();
}

(二)View
这里的View除了Layout布局之外, 还包括View的一些事件的处理, 我们想看Layout
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <!--如果想UserEditText关联起来,需要引入User-->
    <data>

        <variable
            name="event"
            type="com.ctao.demos.blogcodes.mvvm.event.UserEvent" />
    </data>

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

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

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

            <EditText
                android:id="@+id/et_username"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:addTextChangedListener="@{event.usernameWatcher}" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:orientation="horizontal">

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

            <EditText
                android:id="@+id/et_password"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:addTextChangedListener="@{event.passwordWatcher}" />
        </LinearLayout>

        <Button
            android:id="@+id/bt_login"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="20dp"
            android:text="login" />

    </LinearLayout>
</layout>
可以发现, 我们这里的Layout布局和我们之前说些的有点不一样,在我们的根节点外又套了一层<layou>标签。在标签的里面的data标签中声明了一个event类,然后在EditText控件里关联了event里的事件,具体写法也请参看谷歌官方文档, 这里就不细说了。
接下来是处理View事件的UserEvent
//View (Layout组合成View)
public class UserEvent {

    private User user;

    public UserEvent(User user){
        this.user = user;
    }

    public TextWatcher usernameWatcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void afterTextChanged(Editable editable) {
            user.setUsername(editable.toString());
        }
    };

    public TextWatcher passwordWatcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void afterTextChanged(Editable editable) {
            user.setPassword(editable.toString());
        }
    };
}

(三)ViewModel
    在写ViewModel也就是我们Activity之前,  我们先要配置下gredle,配置的要求,在上面第一张图已经说的很明确了。配置好之后,我们同步一下代码, 在我们的build子目录下会自动生成一个xxxBinding.java的类,如图

然后,我们就在Activity中依赖 ActivityMvvmloginBinding这个类,去实现Model和View的关联, 
//ViewModel 通过DataBindingViewModel联系在一起
public class MvvmLoginAvtivity extends AppCompatActivity implements View.OnClickListener {

    private ProgressDialog mPdLoading; // xml中没有, 不能分离
    private User user;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //setContentView
        ActivityMvvmloginBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_mvvmlogin);

        //绑定Event
        user = new User();
        UserEvent userEvent = new UserEvent(user);
        binding.setEvent(userEvent);

        mPdLoading = new ProgressDialog(this);
        findViewById(R.id.bt_login).setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.bt_login:
                login();
                break;
        }
    }

    //登录
    private void login() {
        //业务处理
        mPdLoading.show();
        UserLoginHttp loginHttp = new UserLoginHttp(new Handler());
        loginHttp.login(user.getUsername(), user.getPassword(), new UserLoginHttp.onResultListener<User>() {
            @Override
            public boolean onResult(int state, List<User> data, User result) {
                mPdLoading.dismiss();
                if (state == UserLoginHttp.STATE_SUCCEED) {
                    Toast.makeText(getApplication(), user.getUsername() +
                            " login success , to MainActivity", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(getApplication(),
                            "login failed", Toast.LENGTH_SHORT).show();
                }
                return false;
            }
        });
    }
}
OK, 到此MVVM的一个简单demo就算是完工了, 在实际项目中要使用MVVM着手搭建架构的话, 必须就得对DataBingding的使用异常了解。

总结,由于Android中的MVC模式使得我们的Activity既包含界面相关又包含业务相关,为了减少Activity的职责,衍生了两种解决思路
  • 将Activity中的业务部分拆分出来,既出现了——MVP
  • 将Activity中界面相关内容拆分出来,既出现了—— MVVM


以上是个人学习的一些整理,纯属个人见解,欢迎讨论和吐槽~


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MVCMVPMVVM是常用的软件设计模式,用于分离应用程序的不同组件,提高代码的可维护性和可重用性。以下是它们的概念和区别: 1. MVC模式(模型-视图-控制器):MVC模式是最古老也是最常用的设计模式之一。它将应用程序分为个组件:模型、视图和控制器。模型负责处理数据和业务规则,视图负责展示数据给用户,控制器负责处理用户输入并更新模型和视图。MVC模式通过分离关注点,使得修改一个组件对其他组件没有依赖,增强了代码的可维护性。 2. MVP模式(模型-视图-展示器):MVP模式是基于MVC模式的演化,主要用于桌面和移动应用程序的开发。它与MVC的不同之处在于,视图和控制器被合并成一个展示器,展示器负责处理用户输入、更新模型并更新视图。MVP模式通过与视图分离,使得视图的变化不会影响展示器的逻辑。这样,在测试时可以更轻松地独立对展示器进行单元测试。 3. MVVM模式(模型-视图-视图模型):MVVM模式是一种用于构建用户界面的设计模式。它将视图的状态和行为抽象成一个视图模型,视图模型负责处理用户输入、保存视图状态、与模型进行交互,并通过数据绑定将数据自动更新到视图上。MVVM模式通过数据绑定机制,使得视图和模型之间的通信变得更简单,提高了可维护性和可重用性。它常用于Web前端开发和桌面应用程序的现代界面开发。 总结来说,MVCMVPMVVM种常见的软件设计模式MVC模式是最早的一种,将应用程序分为模型、视图和控制器,用于分离关注点。MVP模式是基于MVC模式的演化,通过将视图和控制器合并成一个展示器,便于测试和维护。MVVM模式是用于构建用户界面的设计模式,通过视图模型和数据绑定机制,实现了视图与模型之间的解耦。每种模式都有自己的特点和适用场景,根据具体需求选择合适的模式可以提高开发效率和代码质量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值