了解架构
- 架构的理解:
- 架构是为了解决某些问题而提出;
- 架构规定了一个系统中的组件/角色/模块的划分规则;
- 架构决定了这些不同的模块/角色的沟通机制;
结构是一种规则,一种架构有很多种实现的方式,没有对错之分,只有合适之分;
-
架构的学习:
学习一个架构,我们要聚焦于架构解决了什么样的问题,从而根据我们遇到的问题去选择合适的架构;重点掌握架构它的思想,它的规则是什么样子的不同的角色是怎么划分的,最后要清楚这个架构的沟通机制;
架构中通信的数据一般分为两种:数据结构,事件;
- 数据结构:网络请求,本地存储通信使用的
javabeen; - 事件:控件产生的动作:触摸,点击,滑动等等;
- 数据结构:网络请求,本地存储通信使用的
-
常见的架构:
常见的有mvc,mvp,mvvm,除了这些,还有cs(客户端-服务端模式),主从模式等等;
MVC
我们学习的线是: 如何划分职责->通信的流程->实现->解决了什么样子的痛点以及优缺点;
如何划分职责
MVC: model, view ,controller
model
-
定义:模型,负责数据的加载和存储;
-
职责:
- 从网络,数据库,文件里面加载或者存储数据;
- 封装业务逻辑:数据效验、数据转换、缓存策略;
- 不直接操作UI;
view
-
定义:视图,负责界面展示;
-
职责:
- 负责UI事件(点击),把用户的操作交给控制器;
- 显示model的数据;
Controller
-
定义:控制器,负责逻辑控制;
-
职责:
- 接收用户的输入;
- 调用model层的方法;
- 通知viiew更新UI;
数据流向:
view产生事件,然后通知给controller, controller作逻辑的处理,然后把数据通知给model,最后model进行数据的处理,最后通知给view更新UI;
具体实现:
-
其实在android 中,可以理解为一个mvc, xml文件就是一个view层,活动或者碎片可以理解为一个控制器层;
-
我们往往会在碎片或者活动中充当controller,model的角色,xml的view->所以碎片和活动中也会有view的角色;
-
引用持有:
-
view中持有controller的引用和model的引用;
-
controller中持有controller的引用;
-
model持有view的引用;
1是因为,我们需要在这里设置,使得2,3成立;
-
-
大致就是:规定三端接口,规定不同的方法,然后让三端实现对应接口的方法;在view调用c的方法,在c处理好数据调用m方法,以此类推;

优缺点
-
优点:
在一定程度上降低了耦合,划分了职责;
-
缺点:
- Fragment/Activity里面还是很臃肿:因为它天然承担一些逻辑,既承担了view的角色,还有controller的角色;
- 解耦:如果直接修改view,controller和model都会受到影响;
- 增加了代码结构的复杂性;
这里我想解释一下1,2;
对于1,view和controller虽然是两个类,但是是碎片决定什么时候调用controller等等,这本来就承担了一部分逻辑;所以会导致碎片较为臃肿;
对于2,为什么view的改动会使得controller,model收到影响;对于controller,比如我要取消某个按钮的点击,那么这个按钮对应的逻辑会失效;对于Model,因为Model持有view的引用,假如本来调用的view的方法是getname(),但是由于业务变动使得这个数据调用的方法是getxb();就会导致model中调用这个方法处全部报错,所以这就是问题了;
MVP
介绍
- MVP是MVC的改进,避免了UI组件直接与业务逻辑的耦合;解决了碎片/活动中臃肿,过渡耦合;
如何划分职责
-
mvp-model、view 、presenter
model
- 负责业务逻辑和数据的 处理,和p通信;
view
- view不包含任何业务逻辑,view通过接口和p通信,把业务逻辑交给p来处理;
presenter
- 作为model,view的中介,负责把model获得数据通知view更新,处理逻辑和决定如何将数据传递给view;
解决的问题
能解决mvc的问题:数据处理逻辑和界面交互相耦合,也能将mvc中的view和Model解耦:mvc中view可能直接访问Model获取数据,耦合度较高,但是mvp中,view不会直接访问Model,而是通过P层进行业务逻辑的处理以及负责view和model的交互;
数据流向
用户触发事件(点击按钮,输入文本)->view收到点击事件之后交给p层->p层做出业务逻辑处理->如有需要,把数据传递给Model->Model更新、储存、获取数据->将结果返回给P层->p层更新UI
具体实现
我的实现想法就是:
- 在活动里持有mvp三层的实例,在这里将p层进行构造方法依赖注入;
- 在v层通过方法注入,获得P层的实例,进行方法调用;
- 在m层可以通过方法注入,也可以通过接口回调(p层实现接口,在方法中传入自己,使得p,m通信,m回调时会回到p层,所以很容易造成接口臃肿);
看了一篇学长的博客,有两处代码需要我们学习:
-
BaseView接口:
- 里面只有一个方法,这个方法的作用是让v层都实现这个方法,获得p层的实例,输入方法注入;
javapublic interface BaseView<T>{ /** * 为视图绑定对应的presenter * * @param presenter */ void setPresenter(T presenter); }- 同时view接口去继承这个baseview接口
javainterface View extends BaseView<Presenter> { void setMusicData(musicData musicData); void showError(); /** * 用于判断Fragment是否成功加入到Activity * * @return {@link Boolean} */ Boolean isACtive(); } ``` -
单例:
虽然但是,你真的打算创建很多model的实例吗?好吧,笔者天气预报就是这么写的,现在看来,,,感觉还是应该把架构好好学学,不然写的代码一坨有什么意义呢?
好吧,那我们需要创建单例:
以下是简单实现:
javapublic class danli { private static danli danli = null; public static danli getInstance(){ if(danli == null){ danli = new danli(); } return danli; } } ```
好吧,其实我看了两位学长的博客,在他的博客里,我需要了解一下依赖注入;
刚说了那么多的注入,泥萌知道指的是啥吗?
好吧,我们刚一直在说,mvc,mvp解决了业务逻辑和UI耦合的问题,实现了解耦,那么到底怎么解耦的?
高内聚,低耦合:类的内部元素(方法定义)应该紧密相关,与外部类的依赖关系应该降低;
-
接口
- 定义了两个模块的交互规则;使得两个模块通过接口交互,不依赖具体的类;
- 举例:view 和 presenter: view可以很容易的替换, 不会依赖具体的view类;
-
依赖注入:
-
介绍:是一种设计模式,将对象的依赖关系从内部创建变成外部传递,从而到达解耦的地步;介绍模块之间的!直接!依赖;
-
实现方法:构造函数注入,方法注入,属性注入;
其实听名字就很好理解了啊,构造函数注入就是通过构造方法传入实例,mvp中就是通过构造函数注入把v,m注入p层的;方法注入就是通过方法调用啊,mvp中在v层就是通过方法注入得到p层的实例的;
但是使用方法注入的时候,要注意的就是,避免在依赖未注入的时候使用对象吧,但是构造方法就安全的多了没有这个担忧;
-

MVP架构的优缺点
-
优点:
- 结构清晰,划分职责清晰;
- 模块间解耦充分;
- 有利于组件的重用;
-
缺点:
- 有大量的接口;
- 代码结构会变得复杂;
MVVM
解决的问题
除了控制逻辑、数据处理逻辑、view交互的耦合之外,不仅解决了mvc中view 和 model耦合的问题;还解决了mvp中view 和 presenter 耦合的问题;
划分职责
- view: 显示UI
- viewmodel: 控制器,处理逻辑
- model :模型,数据的获取和储存;
不同职责如何通信
-
在mvvm中,解耦更彻底,当viewModel发生改变时,会自动通知view界面更新,当view有事件产生时,会自动反馈给viewModel;
-
流程就是:
view产生了事件,自动更新给了viewModel,viewmodel进行逻辑处理之后,通知model数据加载或储存,然后把结果返回给viewmodel,viewmodel最后自动更新给了view;
MVVM的实现
这里主播是通过Livedata+viewmodel+databinding实现的,没学的可以学一下;
这里主播是实现了按钮点击+调用viewmodel的方法+调用Model的方法+回调至viewmodel+动态更新UI;
这里主播还想强调一下,主播看了一个人写的博客,里面写在Model层用viewmodel的实例的方法,主播写了后仍给ai, 结果ai说主播的是mvvm和mvp混合架构,主播很伤心;所以说大家如果想在Model里返回数据可以使用接口回调,标准的mvvm中Model不要过于有viewmodel的实例的;
view层:
java
com.example.mvvm.Swy binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
得到viewmodel的实例,通过方法注入使得viewmodel可以调用Model层的方法;
BookViewModel bookViewModel = new ViewModelProvider(this).get(BookViewModel.class);
Model model = new Model();
bookViewModel.setMode(model);
将databinding和viewmodel联系,这样viewmodel中数据更新的时候会自动更新UI;
binding.setViewmodel(bookViewModel);
binding.setLifecycleOwner(this);
viewmodel层:
java
public class BookViewModel extends ViewModel {
private MutableLiveData<Book> book = new MutableLiveData<>(new Book("",""));
private Model model;
public MutableLiveData<Book> getBook(){
return book;
}
public LiveData<Book> getsingleBook(){
if(book == null){
book = new MutableLiveData<>(new Book("",""));
}
return book;
}
public void setMode(Model mode) {
this.model = (Model) mode;
}
public void getmes(View view) {
Book book1 = book.getValue();
String mes;
Book finalBook = book1;
model.getmes(book1.getId(), new Model.getmesmodel() {
@Override
public void getmesmothod(String s) {
finalBook.setName(s);
book.setValue(finalBook);
}
});
}
public void clearmes(View view) {
model.crearmes();
book.setValue(new Book("",""));
}
}
Model:
java
public class Model {
private Handler handler = new android.os.Handler(Looper.getMainLooper());
public interface getmesmodel{
void getmesmothod(String s);
}
public void getmes(String text,getmesmodel getmesmodel) {
String mes;
handler.post(new Runnable() {
@Override
public void run() {
StringBuilder stringBuilder = new StringBuilder(text);;
stringBuilder.append("喜欢李佳雪");
getmesmodel.getmesmothod(stringBuilder.toString());
}
});
}
public void crearmes() {
}
}
没啥好说的,大家看代码理解即可;

优缺点:
优点:
- 职责划分清晰;
- 模块间充分解耦;
- 在mvp基础上,把view和viewModel进行了充分解耦;
缺点:
- debug困难,由于view和vm解耦;难以看出view事件的传递;
- 复杂性加大;