1、MVP的诞生
以下内容都是从安卓的角度分析:
首先要了解什么是MVC架构:
图片来源网络
- View:对应XML文件及Activity或fragment,因为许多修改视图的操作在Activity中实现;
- Controller:对应Activity;
- Model:业务数据,例如JavaBean等存放数据的类、数据库等。
MVC架构是为了视图与数据的分离,但由图也可见Veiw层跟Model层是直接进行交互的,这也必然会导致它们的耦合。且在Android中可见Activity承担了V层与C层的双重任务,Activity代码量会非常大,也违背了单一职责原则,而MVP可以解决这样的问题。
2、MVP理论
图片来源网络
- Model:数据层
- Veiw:视图层
- Presenter:纽带层,中文翻译为主持人,负责连接View层跟Model层
目的:使View层跟Model层解耦合,在Android开发中减少Activity的负担,因为Activity只需要负责View层。
缺点:因为Presenter跟View是通过接口交互的,所以容易造成接口地狱问题,就是要创建非常多的接口。
3、示例
步骤1:定义View层接口;
步骤2:Activity或fragment实现View层接口;
步骤3:定义Model层接口;
步骤4:实现Model层接口;
步骤5:定义Presenter层接口;
步骤6:实现Presenter接口
结果演示:
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<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:orientation="vertical"
tools:context=".View.MainActivity">
<EditText
android:id="@+id/et_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"/>
<EditText
android:id="@+id/et_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"/>
<Button
android:id="@+id/bt_login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="login"
android:textSize="20dp"/>
</LinearLayout>
步骤1:定义View层接口;
public interface IView {
void isSuccess(); //登录成功
void isFailure(); //登录失败
}
步骤2:Activity或fragment实现View层接口;
public class MainActivity extends AppCompatActivity implements IView{
private EditText etUsername;
private EditText etPassword;
private Button btLogin;
private IPresenter presenter; //presenter对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etUsername=findViewById(R.id.et_username);
etPassword=findViewById(R.id.et_password);
btLogin=findViewById(R.id.bt_login);
presenter=new MainPresenter(this);
initClick();
}
private void initClick() {
btLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String userName=etUsername.getText().toString();
String password=etPassword.getText().toString();
presenter.login(userName,password); //调用Presenter层
}
});
}
@Override
public void isSuccess() {
Toast.makeText(this,"登录成功",Toast.LENGTH_SHORT).show(); //实现接口定义函数
}
@Override
public void isFailure() {
Toast.makeText(this,"登录失败",Toast.LENGTH_SHORT).show(); //实现接口定义函数
}
}
步骤3:定义Model层接口;
public interface IModel {
void login(String username, String password, LoginCallback callback);
}
//登录回调接口
public interface LoginCallback {
void onSuccess();
void onFailure();
}
步骤4:实现Model层接口;
public class Model {
public void login(String userName,String password,LoginCallback loginCallback){
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
if (userName.equals("1")&&password.equals("1"))
loginCallback.onSuccess();
else
loginCallback.onFailure();
}
},1000);
}
}
步骤5:定义Presenter层接口;
public interface IPresenter {
void login(String userName,String password);
}
步骤6:实现Presenter接口
public class MainPresenter implements IPresenter, LoginCallback {
private Model model;
private IView iView;
public MainPresenter(IView iView){
model=new Model();
this.iView=iView;
}
@Override
public void login(String userName,String password) {
model.login(userName,password,this);
}
@Override
public void onSuccess() {
iView.isSuccess();
}
@Override
public void onFailure() {
iView.isFailure();
}
}
运行流程:
1、当用户点击登录时会触发点击监听器,将用户名密码交给presenter层
presenter.login(userName,password);
2、presenter层持有model层的引用,与model进行交互
public void login(String userName,String password) {
model.login(userName,password,this);
}
3、model层处理数据,调用presenter层,presenter实现了LoginCallback接口
public void run() {
if (userName.equals("1")&&password.equals("1"))
loginCallback.onSuccess();
else
loginCallback.onFailure();
}
4、presenter层调用View层接口将数据展示到界面
@Override
public void onSuccess() {
iView.isSuccess();
}@Override
public void onFailure() {
iView.isFailure();
}