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

一、MVC模式在Android中的体现
    MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写。
    对于我们稍有些开发经验的同学们来说, 对MVC应该也是相当的熟悉了。
  • View: 对应于布局文件Layout
  • Controller: 对应于Activity
  • Model :业务逻辑和实体模型
    看起来这的确按照MVC的模式分工的很明确, 但是仔细想想在实际的开发中, View做的事情其实很少, 就一个layout布局文件, 数据的绑定、事件处理全部在Activity中完成的,造成了Activity既像View又像Controller(当然DataBingding的出现——MVVM模式,使得View更像View吧后面会讲到 ),我们看下MVC的一个模型图

好的, 下面以一个简单的登录的来解说Android中的MVC
项目的一个效果图和项目 结构

OK, 接下来开始一步一步的MVC编写思路

(一)、Modle
实体类User这个不用多说, 直接上代码,其次从效果图可以看到至少有一个业务方法login(),这个这里只是模拟的login, 也没什么难的
//Model 实体
public class User {

    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
//Model 业务
public class UserLoginHttp {

    /** 请求异常 */
    public static final int STATE_ERROR = -1;
    /** 请求成功 */
    public static final int STATE_SUCCEED = 0x11;
    /** 请求成功, 无数据 */
    public static final int STATE_SUCCEED_EMPTY = 0x22;
    /** 请求成功, JSON异常 */
    public static final int STATE_SUCCEED_JSON_ERROR = 0x33;
    /** 未请求 */
    public static final int STATE_UNGEBETEN = 0x44;

    public interface onResultListener<T> {
        /**
         * 请求结果返回
         * @param state 状态码
         * @param data List集合返回
         * @param result json字符串返回
         * @return 是否自行处理结果
         */
        boolean onResult(int state, List<T> data, T result);
    }

    //--------------------上部分可抽取为公用, 这里只是简单demo-------------------

    private Handler handler;

    public UserLoginHttp(Handler handler){
        this.handler = handler;
    }

    public void login(final String username, final String password, final onResultListener<User> loginListener) {

        //模拟子线程耗时操作
        new Thread() {
            @Override
            public void run() {
                SystemClock.sleep(2000);
                if ("123".equals(username) && "123".equals(password)) {
                    final User user = new User();
                    user.setUsername(username);
                    user.setPassword(password);
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            loginListener.onResult(STATE_SUCCEED, null, user);
                        }
                    });

                } else {
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            loginListener.onResult(STATE_ERROR, null, null);
                        }
                    });
                }
            }
        }.start();
    }
}

(二)View
上面我们说的, 在我们Android的MVC中, View其实就是Layout布局, 那也不用多说, 这里就直接粘代码了
<?xml version="1.0" encoding="utf-8"?>
<!--View layout-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    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" />
    </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" />
    </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>

(三)Controller
Controller, 其实就是我们的Activity了, 根据不同的业务逻辑去展示我们的View
//Controller Activity
public class MvcLoginActivity extends AppCompatActivity implements View.OnClickListener {

    private ProgressDialog mPdLoading;
    private EditText et_username;
    private EditText et_password;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mvclogin);

        et_username = (EditText) findViewById(R.id.et_username);
        et_password = (EditText) findViewById(R.id.et_password);
        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() {
        //TODO 业务和界面的交互
        mPdLoading.show();
        UserLoginHttp loginHttp = new UserLoginHttp(new Handler());
        loginHttp.login(et_username.getText().toString(), et_password.getText().toString(), new UserLoginHttp.onResultListener<User>() {
            @Override
            public boolean onResult(int state, List<User> data, User user) {
                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;
            }
        });
    }
}
综上, 我们再来总结一下,
这个简单的登录的demo,按照MVC的模式来拆分,包括以下内容
  • View:我们的activity_main布局
  • Controller:我们的MainActivity
  • Model :User实体类和UserLoginHttp业务类
不难发现, 这其中所存在的一些问题,  View 就只有一个Layout,而Activity中存在两部分类容(业务相关+界面相关),随着我们项目需求的增多, 我们会发现Activity会变得越来越庞大,业务和界面结合的越来越密切。
那么,如何解决这其中的问题呢?
    既然Activity是包含了业务相关和界面相关两大模块,我们为何不试着把业务和界面再做一次拆分呢?好的,说拆,咱就拆,
         1、如果将Activity中的业务部分拆分,Activity只负责View的展示,这样 MVP 就诞生了。
         2、如果将Activity中的界面相关内容拆分, Activity只负责一些简单的业务逻辑的处理, 这样 MVVM 模式也诞生了。

ok, 到这MVC模式已经分析的差不多了, 由于部分代码的粘贴,文篇已经比较长了, 就让我们转到下一篇 《浅谈Android中MVC、MVP、MVVM模式(二)》

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


参考资料


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值