架构是什么
架构是为了解决特定的问题而提出来的,而且它还有特定的规则,能够把整个应用的整体进行角色的划分。并且他还能够约定角色之间的联系沟通机制。
所以学习架构要带着以下三个问题去理解:
。架构解决了什么问题?
。架构模式是如何划分角色的?
。角色间是如何建立联系的?
在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布局文件。
代码实例
<?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"><Buttonandroid: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="登录" /><TextViewandroid: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
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() {@Overridepublic void onFailure(Call call, IOException e) {Log.d(TAG, "onFailure");if(null != mListener){mListener.onFail();}}@Overridepublic 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
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();@Overrideprotected 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() {@Overridepublic void onClick(View view) {//请求数据model.login(new LoginModel.OnLoginListener() {@Overridepublic void onSuccess(String data) {//更新UIrunOnUiThread(new Runnable() {@Overridepublic void run() {updateView(data);}});}@Overridepublic 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
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();@Overrideprotected 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() {@Overridepublic void onClick(View view) {loginPresenter.getUserInfo();}});}@Overridepublic void onResult(String data) {Log.d(TAG, "onResult data:" + data);runOnUiThread(new Runnable() {@Overridepublic void run() {textView.setText(data);}});}@Overrideprotected void onDestroy() {super.onDestroy();//释放loginPresenter.detach();}
}
presenter
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";@Overridevoid getUserInfo() {LoginModel model = new LoginModel();model.login(new LoginModel.OnLoginListener() {@Overridepublic void onSuccess(String data) {view.onResult(data);}@Overridepublic void onFail() {}});}
}
model
…
缺点
MVP这种开发模式对于简单的应用程序可能会显得过于复杂,MVP需要开发额外的Presenter类,可能增加开发工作量。为了实现MVP,通常需要定义大量的接口,这可能增加代码的复杂性。
总结
虽然MVP是MVC的优化后的产物,但还是各有利弊的。MVP解决了MVC在复杂项目中导致的Activity代码膨胀和维护难的问题。MVP复用代码的难度更低,实现方式替换起来更灵活。但是MVC的好处就是能够快速开发,在简单的页面上面使用起来非常的容易上手。所以我们到底要选择哪一种开发模式,需要看具体的场景。
Android 学习笔录
Android 性能优化篇:https://qr18.cn/FVlo89
Android Framework底层原理篇:https://qr18.cn/AQpN4J
Android 车载篇:https://qr18.cn/F05ZCM
Android 逆向安全学习笔记:https://qr18.cn/CQ5TcL
Android 音视频篇:https://qr18.cn/Ei3VPD
Jetpack全家桶篇(内含Compose):https://qr18.cn/A0gajp
OkHttp 源码解析笔记:https://qr18.cn/Cw0pBD
Kotlin 篇:https://qr18.cn/CdjtAF
Gradle 篇:https://qr18.cn/DzrmMB
Flutter 篇:https://qr18.cn/DIvKma
Android 八大知识体:https://qr18.cn/CyxarU
Android 核心笔记:https://qr21.cn/CaZQLo
Android 往年面试题锦:https://qr18.cn/CKV8OZ
2023年最新Android 面试题集:https://qr18.cn/CgxrRy
Android 车载开发岗位面试习题:https://qr18.cn/FTlyCJ
音视频面试题锦:https://qr18.cn/AcV6Ap