Andori架构高阶面试题——MVC、MVP、MVVM、组件化、模块化解析
程序员文章站
2022-06-24 22:50:28
MVC1、Android中MVC是什么?特点?Model:针对业务模型建立的数据结构和类(与View无关,只与业务相关)View:XML/JAVA或者JS+HTML进行页面的显示。Activity/Frgament也承担了View的功能。Controller:Android的控制层通常在Activity、Fragment之中。本质就是Controller操作Model层的数据,并且将数据返回给View层展示。2、Android的MVC的缺点:Activity并不是MVC...
MVC
1、Android中MVC是什么?特点?
Model
:针对业务模型建立的数据结构和类(与View无关,只与业务相关)View
:XML/JAVA
或者JS+HTML
进行页面的显示。Activity/Frgament
也承担了View的功能。Controller
:Android
的控制层通常在Activity、Fragment
之中。
本质就是Controller
操作Model
层的数据,并且将数据
返回给View
层展示。
2、Android的MVC的缺点:
Activity
并不是MVC
中标准的Controller
,既有Controller
的职责也有View
的职责,导致Activity
的代码过于臃肿。View层
和Model层
互相耦合,耦合过重
,代码量过大
,不易于开发和维护。
MVP
3、Android中的MVP模式
MVP(Model-View-Presenter)
Model
:主要提供数据的存储功能。Presenter
需要通过Model
存取数据。View
: 负责处理点击事件和视图展示
(Activity、Fragment或者某个View控件
)Presenter
:View和Model
之间的桥梁,从Model
检索数据后返回给View
层。使得M/V
之间不再有耦合关系。
4、MVP和MVC的区别?(2)
MVP
中绝对不允许View
直接访问Model
- 本质是
增加了一个接口
降低一层耦合度
5、MVP的特点
Presenter
完全将Model
和View
解耦,主要逻辑处于Presenter
中。Presenter
和具体View
没有直接关联,通过定义好的接口
进行交互。View
变更时,可以保持Presenter
不变(符合面向对象编程的特点)View
只应该有简单的Set/Get
方法、用户输入、界面展示的内容,此外没有更多内容。低耦合
:Model和View的解耦,决定了该特性。
6、MVP的优点?
- 低耦合:Model、View层的变换不会影响到对方。
- 可重用性:Model层可以用于多个View。比如请求影视数据,可能有多个页面都需要这个功能,但是Model层代码只要有一份就可以了。
方便测试
:可以单独对Model
层和View
层进行测试。
7、MVP的缺点
MVP
的中使用了接口的方式去连接view层
和presenter层
,如果有一个逻辑很复杂的页面,接口会有很多,导致维护接口的成本非常大。解决办法
:尽可能将一些通用的接口作为基类,其他的接口去继承。
8、MVP的实现?
Model层
//Model层-数据的实体类:NetInfo.java
public class NetInfo {
private int code;
private String msg;
public NetInfo(int code, String msg){
this.code = code;
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
//Model层-请求数据时View和Model的交互接口(中间层Presenter去实现):LoadTasksCallBack.java
public interface LoadTasksCallBack<T> {
void onSuccess(T data);
void onFailed();
}
//Model层-任务抽象基类【业务接口】: NetTask.java
public interface NetTask<T> {
void execute(T data, LoadTasksCallBack callBack);
}
/**=============================================
* Model层核心-具体任务【业务的实际操作】:
* 1. 实现Model层获取数据的操作.
* //NetInfoTask.java
*=============================================*/
public class NetInfoTask implements NetTask<String>{
@Override
public void execute(String ip, LoadTasksCallBack callBack) {
if("192.168.1.1".equals(ip)){
callBack.onSuccess(new NetInfo(1, "This is a Msg from " + ip));
}else{
callBack.onFailed();
}
}
}
Presenter层
* 契约接口:
* 存放相同业务的Preenter和View-便于查找和维护
* //NetInfoContract.java
*=============================================*/
public interface NetInfoContract{
//1、Presenter定义了获取数据的方法
interface Presenter{
void getNetInfo(String ip);
}
//2、View中定义了与界面交互的方法
interface View extends BaseView<Presenter> {
void setNetInfo(NetInfo netInfo);
void showError(String msg);
}
}
/**=========================================
* Presenter具体实现:NetInfoPresenter.info
* 1. 分别与View层和Model层Task关联起来(持有了两者的对象)
* 2. 实现接口getNetInfo()用于View层从Model层获取数据
* 3. * 次要实现了Task执行中需要的回调接口-代理完成了View与Model的交互(避免了M/V的直接交互)
*========================================*/
public class NetInfoPresenter implements NetInfoContract.Presenter, LoadTasksCallBack<NetInfo>{
//1. View层
private NetInfoContract.View mView;
//2. Model层任务
private NetTask mNetTask;
//3. 分别与View和Model建立关联
public NetInfoPresenter(NetInfoContract.View view, NetTask netTask){
mNetTask = netTask;
mView = view;
}
//4. 能让View层获取到Model层数据
@Override
public void getNetInfo(String ip) {
mNetTask.execute(ip, this);
}
//5. 实现Model层需要的回调接口-作用是将Model层数据交给View层
@Override
public void onSuccess(NetInfo netInfo) {
mView.setNetInfo(netInfo);
}
@Override
public void onFailed() {
mView.showError("error");
}
}
View层
//BaseView.java
//View层的基类:定义了设置Presenter的接口
public interface BaseView<T> {
void setPresenter(T presenter);
}
//HttpActivity.java
// View层的具体实现:可以是Activity也可以是Fragment
public class HttpActivity extends Activity implements NetInfoContract.View{
//1. 中间代理人
private NetInfoContract.Presenter mPresenter;
Button mGetButton, mSetButton;
TextView mTitleTxtView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_activity_http);
mGetButton = findViewById(R.id.get_fromnet_button);
mSetButton = findViewById(R.id.set_button);
mTitleTxtView = findViewById(R.id.title_textview);
/**==============================================
* 1、给View层设置Presenter和Model层的Task(获取数据)
*===============================================*/
setPresenter(new NetInfoPresenter(this, new NetInfoTask()));
/**==============================================
* 2、View层通过Presenter去获取数据
*===============================================*/
mGetButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//TODO 从网络请求到数据
mPresenter.getNetInfo("192.168.1.1");
}
});
mSetButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mTitleTxtView.setText("Local Msg = Hello");
}
});
}
/**=====================================
* 3、实现View层的三个接口:设置Presenter和View界面相关功能
*====================================*/
@Override
public void setPresenter(NetInfoContract.Presenter presenter) {
mPresenter = presenter;
}
@Override
public void setNetInfo(NetInfo netInfo) {
mTitleTxtView.setText(netInfo.getMsg());
}
@Override
public void showError(String msg) {
mTitleTxtView.setText(msg);
}
}
public interface LoginMVPContract{
//View接口
public interface ILoginView<T>{
public void showLoginSuccess(T data);
public void showLoginFailed(String errorMsg);
}
//任务接口
public interface ILoginTask{
public void startLogin(String phoneNumber, ILoginCallBack callback);
}
//Presenter
public interface ILoginPresenter{
public void startLogin(String phoneNumber);
}
//Presenter和Task间交互的接口
public interface ILoginCallBack<T>{
public void onLoginSuccess(T data);
public void onLoginFailed(String errorMsg);
}
}
2、Model的LoginResultBean和LoginTask.java
public class LoginResultBean {
}
public class LoginTask implements LoginMVPContract.ILoginTask{
@Override
public void startLogin(String phoneNumber, LoginMVPContract.ILoginCallBack callback) {
if(true){
callback.onLoginSuccess(new LoginResultBean());
}else{
callback.onLoginFailed("登录失败");
}
}
}
3、Presenter
public class LoginPresenter implements LoginMVPContract.ILoginPresenter, LoginMVPContract.ILoginCallBack{
LoginMVPContract.ILoginView mLoginView;
LoginMVPContract.ILoginTask mTask;
public LoginPresenter(LoginMVPContract.ILoginView loginView, LoginMVPContract.ILoginTask task){
mLoginView = loginView;
mTask = task;
}
/**
* 接口回调至
*/
@Override
public void onLoginSuccess(Object data) {
mLoginView.showLoginSuccess(data);
}
@Override
public void onLoginFailed(String errorMsg) {
mLoginView.showLoginFailed(errorMsg);
}
@Override
public void startLogin(String phoneNumber) {
mTask.startLogin(phoneNumber, this);
}
}
4、View
public class LoginFragment extends SupportFragment implements LoginMVPContract.ILoginView<LoginResultBean>{
LoginMVPContract.ILoginPresenter mLoginPresenter;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLoginPresenter = new LoginPresenter(this, new LoginTask());
mLoginPresenter.startLogin("17777777777");
}
@Override
public void showLoginSuccess(LoginResultBean data) {
//登陆成功
}
@Override
public void showLoginFailed(String errorMsg) {
//登录失败
}
}
9、怎么优化MVP的类文件量
- 采用
泛型
定义契约类,将model、view、presenter
定义在一个契约类中
- 结构清晰,一个
契约类
对应一个业务模块
。
MVVM
10、MVVM模式的作用和特点?
Model-View-ViewModel
,将Presenter
替换为ViewModel
。ViewModel
和Model/View
进行了双向绑定。View
发生改变时,ViewModel
会通知Model
进行更新数据Model
数据更新后,ViewModel
会通知View
更新显示- 谷歌发布了
MVVM
支持库Data Binding
:能将数据绑定到xml
中- 现在谷歌又推出了
ViewModel和LiveData
组件用于更方便的实现MVVM
MVVM
模块化和组件化
11、什么是模块化
- 一种
软件设计技术
- 将
项目
的功能拆分为独立
、可交换
的模块- 每个
模块
都包含执行单独功能
的必要内容
。
12、什么是组件化
- 组件化软件工程也被成为组件化开发,是一种软件工程的分支。
- 强调将一个软件系统拆分为独立的组件(组件可以使模块也可以是web资源等等)
13、模块化和组件化的区别
- 两者目的都是
重用和解耦
- 主要是
叫法不同
模块化
侧重于重用,组件化
更侧重于业务解耦
14、组件化优点
- 组件间可以灵活组建
- 一个
组件
的更改,只要对外提供的接口
没有变化,则其他组件
不需要再测试。- 缺点:对技术、业务理解度有更高要求。
15、模块化的层次拆分
- 基础库
- 通用业务层
- 应用层
16、模块间通信
- 可以自己实现但比较麻烦
- 建议用
阿里巴巴
的开源库。
看完点赞,养成习惯,微信搜一搜「 程序猿养成中心 」关注这个喜欢写干货的程序员。
另外更有Android一线大厂面试完整考点、资料更新在我的Gitee,有面试需要的朋友们可以去参考参考,如果对你有帮助,可以点个Star哦!
Gitee地址:【老陈的Gitee】
本文地址:https://blog.csdn.net/qq_39477770/article/details/108868865