对数据库的操作。
显示数据和接收用户输入的数据,为用户提供一种交互式操作的界面。
表示为WEB方式、WINFORM方式。
对数据层的操作,对数据业务逻辑处理。
当用户出发事件的时候,
View传送指令到Controller,
Controller完成业务逻辑后,要求Model改变状态,
Model将新的数据发送到View显示,用户得到反馈
Tips:所有的通信都是单向的。
接受用户指令时,MVC可以分为两种方式。一种是通过View接受指令,传递给Controller;另一种是直接通过Controller接受指令。
负责数据存取。
处理数据显示。
处理业务逻辑。
负责从视图读取数据,控制用户输入,并向模型发送数据。比如:写入数据库记录
MVC是复合模式,结合了:观察者模式、策略模式、组合模式。
结合两个或两个以上的模式,组成一个解决方案,解决一再发生的一般性问题。
模型是被观察者。
同一个模型可同时使用多个视图,当状态改变时,相关对象将持续更新。
控制器是视图的策略。
视图只关心系统中可视的部分,对于任何界面行为,都委托给控制器处理。
控制器负责和模型交互来传递用户请求,对于工作是怎么完成的,视图毫不知情。
视图使用组合模式实现用户界面。
用户界面通常组合了嵌套的组件,像面板、框架和按钮。
缺点:view层和model层相互可知,可能存在耦合。(演化出了MVP、MVVM这两种框架)
对于原生的android项目:
java bean,类似repository类(spring中的注解:@Repository用于标注数据访问组件,即DAO组件)
注意:
对数据库的操作、网络等操作都应该放在model里面处理,当然对业务计算等操作也应该放在该层。
layout.xml、JS+html
各类activity。
**注意:
不要在activity中写代码,要通过activity交割model业务逻辑处理,这样避免了activity执行耗时操作。**
为了解决MVC耦合过重的问题,MVP的核心思想就是提供一个Presenter将视图逻辑I和业务逻辑相分离,达到解耦的目的。
提供数据。
activity和fragment。用于显示数据。
负责逻辑的处理,处理关于用户事件的转发。
view层和presenter层的通信是通过接口实现的:activity、fragment可以去实现定义好的接口,而在对应的presenter中通过接口调用方法。
如果要实现的UI比较复杂,而且相关的显示逻辑还跟Model有关系,就可以在View和Presenter之间放置一个Adapter。由这个 Adapter来访问Model和View,避免两者之间的关联。而同时,因为Adapter实现了View的接口,从而可以保证与Presenter之间接口的不变。这样就可以保证View和Presenter之间接口的简洁,又不失去UI的灵活性。
view层和model层不再相互可知,解耦。Presenter完全把Model和View进行了分离。通过MVP模式,可以编写测试用的View,模拟用户的各种操作,从而实现对Presenter的测试。这就解决了MVC模式中测试,维护难的问题。
在MVP模式里,View只应该有简单的Set/Get的方法,用户输入和设置界面显示的内容,除此就不应该有更多的内容,绝不容许直接访问Model–这就是与MVC很大的不同之处。
Android中最早的方案。Activity/Fragment这些上帝角色既承担了V的角色,也承担了C的角色,小项目开发起来十分顺手,大项目就会遇到耦合过重,Activity/Fragment类过大等问题。
所有View的基类。以接口形式实现。
i>其中方法:
getContext方法必须有。
余下方法可根据需要自行创建。笔者这创建的其余3个方法是对话框方法。是为了在CouponPresenter中可以直接调用对话框:basalView.showCircleProgressDialog();
。
ii>关联性
BasalAcivity、BasalFragment实现该接口和其中所有方法,避免在每个Acitivity中实现这些方法。
iii>代码
public interface BasalView {
Context getContext();
void showCircleProgressDialog();
void showToastShort(String message);
void dismissCircleProgressDialog();
void clearCircleProgressDialog();
}
契约类。所有Contract基类。
contract包定义了一系列的接口,用于联系View层和Presenter层。
i>方法:
两个方法,顾名思义,用来绑定和解除View。
ii>关联性:
所有contract接口实现该接口。
iii>代码:
public interface BasalContract<T extends BasalView> {
void attachView(T basalView);
void detachView();
}
Acitivity基类。
i>关联性:
a.实现BasalView接口及其中方法
b.泛型类,绑定Presenter。
重点在于在initialize方法种绑定了Presenter,在onDestroy方法中解绑了Presenter。其余方法可根据需求自定义添删。
在具体的Acitivity中,通过initPresenter方法返回具体的Presenter.
c.抽象类。所有Activity继承此类。
ii>代码:
public abstract class BasalActivity<T extends BasalContract> extends AppCompatActivity implements BasalView {
public T presenter;
/**
* 获取布局资源
*
* @return
*/
protected abstract int getLayoutId();
/**
* 初始化布局控件
*/
protected abstract void initView();
/**
* 初始化Presenter
*
* @return
*/
protected abstract T initPresenter();
/**
* 加载数据
*/
protected abstract void loadData();
/**
* 为控件绑定事件
*/
protected abstract void viewOption();
@Override
protected void onCreate(Bundle savedInstanceState) {
// removeStatusBar();
super.onCreate(savedInstanceState);
setContentView(getLayoutId());
initialize();
}
private void initialize() {
presenter = initPresenter();
if (presenter != null) {
presenter.attachView(this);
}
initView();
loadData();
viewOption();
}
@Override
public Context getContext() {
return getActivity();
}
protected Activity getActivity() {
return this;
}
@Override
protected void onDestroy() {
if (presenter != null) {
presenter.detachView();
}
clearCircleProgressDialog();
super.onDestroy();
}
//转圈
private CircleProgressDialog circleProgressDialog;
@Override
public void showToastShort(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
@Override
public void showCircleProgressDialog(){
if (null == circleProgressDialog){
circleProgressDialog = new CircleProgressDialog(this);
circleProgressDialog.setCancelable(false);
}else{
dismissCircleProgressDialog();
}
circleProgressDialog.showDialog();
}
@Override
public void dismissCircleProgressDialog(){
if (null != circleProgressDialog) {
circleProgressDialog.dismiss();
}
}
@Override
public void clearCircleProgressDialog(){
if (null != circleProgressDialog) {
circleProgressDialog.dismiss();
}
circleProgressDialog = null;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
protected void removeStatusBar() {
// 当系统版本为4.4或者4.4以上时可以使用沉浸式状态栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
}
}
Fragment基类。类似BasalActivity。
在此处仅贴出重要部分代码。
public abstract class BasalFragment<T extends BasalContract> extends Fragment implements BasalView {
protected T presenter;
Context context = null;
private View rootView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(getLayoutId(), container, false);
ButterKnife.bind(this, rootView);
context = getActivity();
initialize();
return rootView;
}
protected void initialize() {
presenter = initPresenter();
if (presenter != null) {
presenter.attachView(this);
}
initView();
loadData();
viewOption();
}
@Override
public void onDestroyView() {
if (presenter != null) {
presenter.detachView();
}
super.onDestroyView();
}
/**
* 初始化presenter
*
* @return
*/
protected abstract T initPresenter();
/**
* 初始化视图控件
*/
protected abstract void initView();
/**
* 加载数据
*/
protected abstract void loadData();
/**
* 绑定事件
*/
protected abstract void viewOption();
/**
* 获取布局资源文件
*
* @return
*/
protected abstract int getLayoutId();
@Override
public Context getContext() {
return getActivity();
}
Presenter基类。
public abstract class BasalPresenter<T extends BasalView> implements BasalContract<T>{
protected Context context;
protected T baselView;
@Override
public void attachView(T basalView) {
this.baselView = basalView;
context = baselView.getContext();
}
@Override
public void detachView() {
baselView = null;
}
}
该处举例一个优惠券功能的获取,并填充界面的功能。
i>关联性
由于在BasalPresenter中已经实现了BasalContract,对View已经绑定,在此不再实现。
在这个方法中定义其对应的Presenter中具体应该做什么方法。
ii>代码
public interface CouponContract {
void getCouponData(final int page, String typeStr);
}
这个类
i>关联性
实现对应的Contract接口。继承BasalPresenter,并传入对应的View(如CouponView)。
获取到数据后,进行处理,然后通过basalView.方法
,传给对应界面(如实现了CouperView的CouponFragment)
ii>代码
public class CouponPresenter extends BasalPresenter<CouponView> implements CouponContract {
@Override
public void getCoupon(GetCouponRequest getCouponRequest,final int page, String typeStr) {
basalView.showCircleProgressDialog();
getCouponRequest.request(context, page + "", typeStr).setOnRequestListener(new OnRequestListener() {
@Override
public void resultBack(RequestDataBean requestDataBean) {
basalView.dismissCircleProgressDialog();
basalView.getCouponListSuccess(page,requestDataBean);
}
@Override
public void onError(Throwable e) {
basalView.dismissCircleProgressDialog();
basalView.getCouponListFall();
}
});
}
}
i>方法:
对应Fragment或Acitivity中,需要填充数据的地方。
ii>代码
public interface CouponView extends BasalView {
void getCouponListSuccess(int page, RequestDataBean requestDataBean);
void getCouponListFall();
}
具体显示界面的类。
i>方法
initPresenter()方法中返回具体的Presenter。
ii>关联性
继承BasalFragment,并指定泛型CouponPresenter。
实现CouponView,并实现其中方法。在这些方法中我们会获取对应的数据,只需要进行数据的填充即可。需要进行的逻辑处理可在对应的Presenter中进行。
iii>代码
仅显示关键部分代码:
public class CouponFragment extends BasalFragment<CouponPresenter> implements CouponView {
@Override
protected void loadData() {
presenter.getCoupon(getCouponRequest, pageList, couponType);
}
@Override
protected void viewOption() {
}
@Override
protected int getLayoutId() {
return R.layout.fragment_coupon;
}
@Override
protected CouponPresenter initPresenter() {
return new CouponPresenter();
}
@Override
protected void initView() {
setCouponRecyclerView();
}
@Override
public void getCouponListSuccess(int page, RequestDataBean requestDataBean) {
resultSuccess(page, requestDataBean);
}
@Override
public void getCouponListFall() {
}
}
最早由微软提出的。
MVVM模式将Presenter改名为ViewModel,基本上与MVP模式完全一致。
唯一的区别是,它采用双向绑定(data-binding):View的变动,自动反映在ViewModel,反之亦然。
这套框架最早使用的data-binding将数据绑定到xml里,这么做在大规模应用的时候是不行的,不过数据绑定是一个很有用的概念,后续Google又推出了ViewModel组件与LiveData组件。
ViewModel组件规范了ViewModel所处的地位、生命周期、生产方式以及一个Activity下多个Fragment共享ViewModel数据的问题。LiveData组件则提供了在Java层面View订阅ViewModel数据源的实现方案。