一、MVC基本概念

MVC(Model-View-Controller,模型-视图-控制器)模式在Android中曾经是比较流行的架构设计模式;使用MVC设计模式的好处UI界面与业务逻辑数据的分离,在修改或者优化界面及用户交互的同时,无需重新编写业务逻辑。Android中的MVC的角色如下:

  • 模型层(Model):是用进行业务逻辑的处理,比如一些网络访问操作、数据库的操作等等,总之一些耗时操作的任务。
  • 视图图(View):主要是处理数据显示的部分,在Android中xml布局就可以视为V层。
  • 控制层(Controller):在Android中,Activity是处理用户交互问题,因此通常把Activity或者Fragment视为控制器,通过C层来操作M层获取数据,并把数据返回给V层显示

二、MVC基本使用

项目目录结构分成了三个目录,分别是model、controller、listener,其中model目录下存放一些javabean类和业务数据获取接口及其实现类(网络访问);controller目录存放Activity或者Fragment;listener目录下是存放网络访问操作结果的回调接口,目的是将数据返回给View层显示。下面一个简单登录为例:

android开发mvc详解 android mvc_MVC

LoginListener接口:其实这个接口实现回调也相当于model层中一部分。

/**
 * desc:登录回调监听
 */

public interface LoginListener<T> {

    /*请求前一些准备,比如加载提示等待*/
    void onStart_();

    /*访问成功调用*/
    void onSuccess(T t);

    /*访问失败*/
    void onFailed();

    /*访问结束*/
    void onFinish();

}

Model层:

/**
 * desc: 用户信息实体类
 */

public class UserInfo {

    private String userName;

    private String sex;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}
/**
 * desc: login-Model
 */

public interface LoginModel<T>{

    void getUserInfo(String userName, String pwd, LoginListener<T> listener);
}
/**
 * desc:LoginModel的实现类,网络异步访问
 */

public class LoginModelImpl implements LoginModel<UserInfo>{

    @Override
    public void getUserInfo(String userName, String pwd, LoginListener<UserInfo> listener) {

        UserInfo userInfo = new UserInfo();
        userInfo.setUserName(userName);
        //下面是模拟网络访问结果的调用
        listener.onStart_();
        if (!TextUtils.isEmpty(userName) && !TextUtils.isEmpty(pwd)){
            listener.onSuccess(userInfo);
        }else {
            listener.onFailed();
        }
        listener.onFinish();

    }


}

View层:xml布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <EditText
        android:id="@+id/et_user_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPersonName"/>

    <EditText
        android:id="@+id/et_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPassword"/>

    <Button
        android:id="@+id/but_login"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="登录"/>
</LinearLayout>

Controller层:

public class MainActivity extends AppCompatActivity implements LoginListener<UserInfo> {

    private EditText mEtName;
    private EditText mEtPassword;
    private Button mButLogin;
    private LoginModelImpl mLoginModel;
    private ProgressDialog mProgressDialog;

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

        mEtName = findViewById(R.id.et_user_name);
        mEtPassword = findViewById(R.id.et_password);
        mButLogin = findViewById(R.id.but_login);
        mLoginModel=new LoginModelImpl();
        mButLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //登录
                String userName = mEtName.getText().toString();
                String pwd = mEtPassword.getText().toString();
                mLoginModel.getUserInfo(userName,pwd,MainActivity.this);
            }
        });

    }

    @Override
    public void onStart_() {
        Log.d(TAG, "onStart_: ");
        mProgressDialog=new ProgressDialog(this);
        mProgressDialog.setTitle("请求中……");
        mProgressDialog.show();
    }

    @Override
    public void onSuccess(UserInfo userInfo) {
        Log.d(TAG, "onSuccess: ");
        mProgressDialog.dismiss();
        Toast.makeText(this,"登录成功",Toast.LENGTH_SHORT).show();
    }


    @Override
    public void onFailed() {
        Log.d(TAG, "onFailed: ");
        Toast.makeText(this,"登录失败",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onFinish() {
        Log.d(TAG, "onFinish: ");
        mProgressDialog.dismiss();
    }

    private static final String TAG = "MainActivity";
}

上面例子是MVC的简单运用,当你点击登录就是获取登录数据,通过modle层中的接口实现类(LoginModelImpl)来获取网络数据,并把数据返回View层显示交互,从上面例子可以看出,Controller控制器Activity一定程度上实现了视图UI层与数据Modle层的解耦,将View层和Modle
层进行了分离,但并不是十分完美,就是在Controller层Activity中同时存在布局视图初始化和业务逻辑操作响应,也就是View层初始化和Controller层同时绑定到同一类中。当业务越来越复杂时,Activity的职责会越来越多,代码会越来越浮肿,不利于后期的维护。

Android架构设计之MVP模式