架构是什么
架构是为了解决特定的问题而提出来的,而且它还有特定的规则,能够把整个应用的整体进行角色的划分。并且他还能够约定角色之间的联系沟通机制。
所以学习架构要带着以下三个问题去理解:
。架构解决了什么问题?
。架构模式是如何划分角色的?
。角色间是如何建立联系的?
在Android当中,经常被大家提及到就是MVC、MVP和MVVM。本文来分析一下MVC、MVP各自是怎么实现的,怎么写的,以及解决了什么问题而提出来的。
MVC
什么是MVC架构
MVC的话它本来不属于Android的架构模式,而是来自于web前端。在Android发展的前期照搬了前端这一套模式。
MVC模式就是Model、View和Controller。View的职责就是处理显示相关的逻辑以及接收用户行为。再把用户行为转发到Controller,Controller再根据请求去更新或者是获取Model层的数据。Controller更像是一个中转站或者是调度站。Model 负责管理数据、执行业务逻辑。MVC在前端的作用是为了分离数据和视图这两层,但是在Android上面它就不灵光了。
在Android语境下,这里的Controller一般特指Activity和Fragment。而Model可以是 Java 类、数据库、网络请求或其他数据源,就是负责数据的读取操作的。而View的话一般来说是指XML布局文件。
代码实例
view
ini
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".mvc.MvcActivity">
<Button
android:id="@+id/bt_mvc_login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="20dp"
android:text="登录" />
<TextView
android:id="@+id/tv_mvc_response"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/bt_mvc_login"
android:layout_marginTop="20dp"
android:padding="5dp"
android:text="data:"/>
</androidx.constraintlayout.widget.ConstraintLayout>
model
java
public class LoginModel {
private static final String TAG = "LoginModel";
private static final String URL = "https://api.cdnjs.com/libraries/jquery/3.5.1";
private OnLoginListener mListener;
public interface OnLoginListener {
void onSuccess(String data);
void onFail();
}
public void login(OnLoginListener listener) {
mListener = listener;
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(URL)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure");
if(null != mListener){
mListener.onFail();
}
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String message = response.body().string();
Log.d(TAG, "onResponse:" + message);
if(null != mListener){
mListener.onSuccess(message);
}
}
});
}
}
control
typescript
public class MvcActivity extends AppCompatActivity {
private static final String TAG = "MvcActivity";
private LoginModel model;
private Button button;
private TextView textView;
private Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mvc);
button = findViewById(R.id.bt_mvc_login);
textView = findViewById(R.id.tv_mvc_response);
model = new LoginModel();
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//请求数据
model.login(new LoginModel.OnLoginListener() {
@Override
public void onSuccess(String data) {
//更新UI
runOnUiThread(new Runnable() {
@Override
public void run() {
updateView(data);
}
});
}
@Override
public void onFail() {
}
});
}
});
}
private void updateView(String data) {
textView.setText(data);
}
}
上面的代码简单实现了在点击登录按钮后获取数据显示到 TextView。
缺点
很明显,这种开发模式它的缺点就是当页面逻辑复杂时,容易导致Activity的代码膨胀。可能一个Activity当中它的代码量分分钟可以标到上千行。如果要修改某一处业务逻辑的话,有可能去找某个方法就要找半天,原因是Layout布局无法帮助Controller分担数据绑定的逻辑。
Activity虽然能够作为一个很称职的MVC Controller,但是作为一个类来说,它的职责太多了,需要实现的代码也太多了。首先从性能角度出发,Activity在使用期间会有大量的时间驻留在内存中,如果它的代码太多,就会导致性能问题。第二个也是最重要的,就是从分层架构的角度来说。如果某个层次过厚是不利于解耦的,我们就需要对这个层进行更细的拆分。
MVP
什么是MVP架构
后来为了解决Activity任务过于繁重,数据层与视图层交织在一起的问题,演化出来的MVP模式。它的主要特性就是让视图层和数据层分离。
Activity 和 Fragment 视为View层,负责处理 UI和用户交互;
Presenter 为业务处理层,负责处理业务逻辑和发起数据的请求;
Model 层中包含着具体的数据请求,数据源。
这三者之间的关系是View调用Presenter,然后再调用Model去完成数据的请求动作。Model通过callback把数据回传给Presenter,然后Presenter再通过他持有的View接口,把数据回传到View层更新UI。
代码实例
将上面的mvc改成mvp
view
typescript
public class MvpActivity extends AppCompatActivity implements LoginContract.View{
private static final String TAG = "MvpActivity";
private LoginPresenter loginPresenter;
private Button button;
private TextView textView;
private Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mvc);
button = findViewById(R.id.bt_mvc_login);
textView = findViewById(R.id.tv_mvc_response);
loginPresenter = new LoginPresenter();
loginPresenter.attach(this);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
loginPresenter.getUserInfo();
}
});
}
@Override
public void onResult(String data) {
Log.d(TAG, "onResult data:" + data);
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText(data);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
//释放
loginPresenter.detach();
}
}
presenter
scala
public interface BaseView {
}
public class BasePresenter<IView extends BaseView> {
protected IView view;
/**
* 绑定view
* @param view
*/
public void attach(IView view) {
this.view = view;
}
public void detach() {
view = null;
}
}
public interface LoginContract {
interface View extends BaseView {
void onResult(String data);
}
//定义的每个方法都会在view结构当中存在与之相对应的回调方法
abstract class Presenter extends BasePresenter<View> {
abstract void getUserInfo();
}
}
public class LoginPresenter extends LoginContract.Presenter {
private static final String TAG = "LoginPresenter";
@Override
void getUserInfo() {
LoginModel model = new LoginModel();
model.login(new LoginModel.OnLoginListener() {
@Override
public void onSuccess(String data) {
view.onResult(data);
}
@Override
public void onFail() {}
});
}
}
model
...
缺点
MVP这种开发模式对于简单的应用程序可能会显得过于复杂,MVP需要开发额外的Presenter类,可能增加开发工作量。为了实现MVP,通常需要定义大量的接口,这可能增加代码的复杂性。
总结
虽然MVP是MVC的优化后的产物,但还是各有利弊的。MVP解决了MVC在复杂项目中导致的Activity代码膨胀和维护难的问题。MVP复用代码的难度更低,实现方式替换起来更灵活。但是MVC的好处就是能够快速开发,在简单的页面上面使用起来非常的容易上手。所以我们到底要选择哪一种开发模式,需要看具体的场景。