您的位置:首页 > 移动开发 > Android开发

Android中MVC、MVP、MVVM模式<一>

2016-11-24 15:41 337 查看
完整代码: https://github.com/fenggit/Lesson01-mvc-mvp-mvvm

效果图:



一. Android中的MVC模式

1. 对应关系

MVCMCV
全称ModelControllerView
含义模型控制层界面
对应Android的模块网络请求,数据库Activity、Fragment自定义View、layout布局(xml文件)

2. 关系图



3. 登录模块常见写法

登录模块功能:

输入用户名和密码

校验用户是否输入用户名和密码

请求服务器

具体实现:



代码结构



具有实现

LoginActivity代码


public class LoginActivity extends AppCompatActivity {
private EditText mUserView;
private EditText mPasswordView;
private Button mLoginView;

private ProgressDialog mProgressDialog;

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

mUserView = (EditText) findViewById(R.id.et_user);
mPasswordView = (EditText) findViewById(R.id.et_password);
mLoginView = (Button) findViewById(R.id.btn_login);

mLoginView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
login();
}
});
}

/**
* 登录
*/
public void login() {
String user = mUserView.getText().toString();
String pwd = mPasswordView.getText().toString();

if (checkInput(user, pwd)) {
mProgressDialog = ProgressDialog.show(this, null, "正在登录");

// 模拟请求数据
new Thread(new Runnable() {
@Override
public void run() {
// 假设请求数据1秒
SystemClock.sleep(1000);

// 更新UI
runOnUiThread(new Runnable() {
@Override
public void run() {
mProgressDialog.dismiss();
Toast.makeText(getBaseContext(), "登录成功", Toast.LENGTH_SHORT).show();
}
});

}
}).start();
}

}

/**
* 检查输入是否合法
*
* @param user
* @param pwd
* @return
*/
public boolean checkInput(String user, String pwd) {
if (TextUtils.isEmpty(user)) {
Toast.makeText(this, "请输入用户名", Toast.LENGTH_SHORT).show();
return false;
}

if (TextUtils.isEmpty(pwd)) {
Toast.makeText(this, "请输入密码", Toast.LENGTH_SHORT).show();
return false;
}
return true;
}
}


布局代码activity_login.xml


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="16dp"
tools:context="com.fenggit.lesson01.login.LoginActivity">

<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="用户名:" />

<EditText
android:id="@+id/et_user"
android:layout_width="match_parent"
android:layout_height="48dp"
android:hint="请输入用户名" />
</LinearLayout>

<LinearLayout
android:id="@+id/email_login_form"
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="密码:" />

<EditText
android:id="@+id/et_password"
android:layout_width="match_parent"
android:layout_height="48dp"
android:hint="请输入密码"
android:inputType="textPassword" />
</LinearLayout>

<Button
android:id="@+id/btn_login"
style="?android:textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="登录"
android:textAllCaps="false"
android:textStyle="bold" />
</LinearLayout>


常规实现的问题

Activity类包含内容:网络请求+业务相关+界面相关

导致Activity类的庞大的,耦合度高,不利于扩展

4. 通过MVC模式改造登录模块

代码结构



剥离Activity中的网络请求模块到Model中,减轻Activity类的负担,这样Model层需要变更不需要变更Activity类

具有实现

将常规实现
login()
的实现更改为:

/**
* 登录
*/
public void login() {
String user = mUserView.getText().toString();
String pwd = mPasswordView.getText().toString();

if (checkInput(user, pwd)) {
mProgressDialog = ProgressDialog.show(this, null, "正在登录");
// 使用model层
mLoginRequest.request(user, pwd, new LoginRequest.ResultListener() {
@Override
public void onSuccess() {
// 更新UI
runOnUiThread(new Runnable() {
@Override
public void run() {
mProgressDialog.dismiss();
Toast.makeText(getBaseContext(), "登录成功", Toast.LENGTH_SHORT).show();
}
});
}

@Override
public void onFail() {

}
});
}
}


添加
model模块,LoginRequest 请求数据类


public class LoginRequest {
/**
* 模拟请求网络数据
*
* @param user
* @param pwd
* @param resultListener
* @return
*/
public boolean request(final String user, final String pwd, final ResultListener resultListener) {
// 模拟请求数据
new Thread(new Runnable() {
@Override
public void run() {
// 假设请求数据1秒
SystemClock.sleep(1000);
Log.e("LoginRequest", "请求数据:" + user + "," + pwd);

if (resultListener != null) {
// 密码和用户是123 则登录成功
if("123".equals(user)&&"123".equals(pwd)){
resultListener.onSuccess();
}else{
resultListener.onFail();
}
}

}
}).start();

return true;
}

public interface ResultListener {
public void onSuccess();

public void onFail();

}
}


view
模块可以自定义view,而Android中layout中xml就是view模块

MVC实现的问题

Activity类包含内容:业务相关+界面相关

总体来说减轻了Activity的职责,但是业务和界面还是在Activity模块中;

解决方式:

如果将Activity中的业务拆分–>MVP

如果将Activity中的界面控件拆分–>MVVM

二. Android中的MVP模式

1. 对应关系

MVPMVP
全称ModelViewPresenter
含义模型界面连接View和Model的桥梁
对应Android模块网络请求,数据库自定义View、layout布局(xml文件)业务逻辑
Presenter链接View和Model,使用接口进行隔离Activity业务和View.

2. 关系图



与MVC明显的特点就是View和Model不可以直接通信

3. 通过MVP模式改造登录模块

代码结构



其中:

LoginRequest
为Model层,主要是网络请求相关;

LoginPresenter
为Presenter层,主要是登录模块业务层

ILoginView
为View层,主要是关联业务和UI操作,传递接口而不传递Activity和Fragment主要是为了通用性,Presenter业务操作完需要更新UI。

LoginActivity
为纯界面相关操作,实现
ILoginView
接口

具有实现

其中
LoginRequest
和上面一样,Model不变;

添加Presenter层
LoginPresenter
业务层

public class LoginPresenter {
private Context context;
private LoginRequest mLoginRequest;
// 这里传入接口,主要为了通用性,界面可能是Activity和Fragment
private ILoginView mView;

public LoginPresenter(Context context, ILoginView view) {
this.context = context;
this.mView = view;
this.mLoginRequest = new LoginRequest();
}

/**
* 登录
*
* @param user
* @param pwd
*/
public void login(String user, String pwd) {
mLoginRequest.request(user, pwd, new LoginRequest.ResultListener() {
@Override
public void onSuccess() {
// 登录成功,新UI
mView.success();
}

@Override
public void onFail() {
// 登录失败,新UI
mView.fail();
}
});
}

/**
* 检查输入是否合法
*
* @param user
* @param pwd
* @return
*/
public boolean checkInput(String user, String pwd) {

if (TextUtils.isEmpty(user)) {
Toast.makeText(context, "请输入用户名", Toast.LENGTH_SHORT).show();
return false;
}

if (TextUtils.isEmpty(pwd)) {
Toast.makeText(context, "请输入密码", Toast.LENGTH_SHORT).show();
return false;
}
return true;
}
}


添加
View层接口ILoginView


public interface ILoginView {
/**
* 登录成功
*/
void success();
/**
* 登录失败
*/
void fail();
}


更改
LoginActivity
代码,此类只保留UI相关操作

public class LoginActivity extends AppCompatActivity implements ILoginView {
private EditText mUserView;
private EditText mPasswordView;
private Button mLoginView;

private ProgressDialog mProgressDialog;

private LoginPresenter mLoginPresenter;

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

mUserView = (EditText) findViewById(R.id.et_user);
mPasswordView = (EditText) findViewById(R.id.et_password);
mLoginView = (Button) findViewById(R.id.btn_login);

// 第一个是Context对象,第二个是ILoginView
mLoginPresenter = new LoginPresenter(this, this);

mLoginView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
login();
}
});
}

/**
* 登录
*/
public void login() {
String user = mUserView.getText().toString();
String pwd = mPasswordView.getText().toString();

if (mLoginPresenter.checkInput(user, pwd)) {
mProgressDialog = ProgressDialog.show(this, null, "正在登录");
mLoginPresenter.login(user, pwd);
}
}

public void success() {
runOnUiThread(new Runnable() {
@Override
public void run() {
mProgressDialog.dismiss();
Toast.makeText(getBaseContext(), "登录成功", Toast.LENGTH_SHORT).show();
}
});
}

public void fail() {
runOnUiThread(new Runnable() {
@Override
public void run() {
mProgressDialog.dismiss();
Toast.makeText(getBaseContext(), "登录失败", Toast.LENGTH_SHORT).show();
}
});
}
}


MVP实现的问题

主要就是分解Activity职责,原本Activity包含:网络请求+业务相关+界面相关等三个模块,现在完全解耦合;网络请求数据由model层处理,业务相关由presenter处理,而界面View层由Activity处理UI和layout中xml布局;

三. Android中的MVVM模式

未完待续,见下一篇博客

完整代码: https://github.com/fenggit/Lesson01-mvc-mvp-mvvm
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android mvp MVC MVVM