mvc mvp mvvm
来源:互联网 发布:无头骑士异闻录 知乎 编辑:程序博客网 时间:2024/06/16 12:05
一:MVC(Model-View-Controller)是最常见的软件架构之一,业界有着广泛应用。
1:MVC
- 视图(View):用户界面。
- 控制器(Controller):业务逻辑
- 模型(Model):数据保存
- 通讯方式(MVC与Android的各个组件的对应关系):
- View 自定义View或ViewGroup,负责将用户的请求通知Controller,并根据model更新界面
- Controller 完成业务逻辑后,Activity或者Fragment,接收用户请求要求 Model 改变状态
- Model 将新的数据发送到 View,用户得到反馈
2、互动模式:接受用户指令时,MVC 可以分成两种方式。一种是通过 View 接受指令,传递给 Controller。
另一种是直接通过controller接受指令。
![](http://image.beekka.com/blog/2015/bg2015020106.png)
1. 用户可以向 View 发送指令(DOM 事件),再由 View 直接要求 Model 改变状态。
2. 用户也可以直接向 Controller 发送指令(改变 URL 触发 hashChange 事件),再由 Controller 发送给 View。
3. Controller 非常薄,只起到路由的作用,而 View 非常厚,业务逻辑都部署在 View。所以,Backbone 索性取消了 Controller,只 保留一个 Router(路由器) 。
、
View实现:
public class TrackCtrlView implements View.OnClickListener{ private ImageView btnStartTrack, btnStopTrack, btnPauseTrack; private TrackCtrlViewListener listener; private TrackRecordInfo trackRecordInfo; public TrackCtrlView(Activity activity, TrackCtrlViewListener listener){ this.listener = listener; btnStartTrack = (ImageView) activity.findViewById(R.id.btnStartTrack); btnStopTrack = (ImageView) activity.findViewById(R.id.btnStopTrack); btnPauseTrack = (ImageView) activity.findViewById(R.id.btnPauseTrack); btnStartTrack.setOnClickListener(this); btnStopTrack.setOnClickListener(this); btnPauseTrack.setOnClickListener(this); btnPauseTrack.setOnClickListener(this); } /** * 将用户请求通知Controller */ @Override public void onClick(View v) { switch(v.getId()){ case R.id.btnStartTrack: if(listener != null){ listener.trackStatusRequest(TrackRecordStatus.Recording); } break; case R.id.btnStopTrack: if(listener != null){ listener.trackStatusRequest(TrackRecordStatus.Stoped); } break; case R.id.btnPauseTrack: if(listener != null){ if(trackRecordInfo.status == TrackRecordStatus.Paused){ listener.trackStatusRequest(TrackRecordStatus.Recording); }else{ listener.trackStatusRequest(TrackRecordStatus.Paused); } } break; default: break; } } private void refreshView(){ TrackRecordStatus trackStatus = trackRecordInfo == null ? TrackRecordStatus.Stoped : trackRecordInfo.status; if (trackStatus == TrackRecordStatus.Recording) { btnStartTrack.setVisibility(View.GONE); btnPauseTrack.setVisibility(View.VISIBLE); btnStopTrack.setVisibility(View.VISIBLE); btnPauseTrack.setImageResource(R.drawable.btn_track_ctrl_pause); } else if (trackStatus == TrackRecordStatus.Paused) { btnStartTrack.setVisibility(View.GONE); btnPauseTrack.setVisibility(View.VISIBLE); btnStopTrack.setVisibility(View.VISIBLE); btnPauseTrack.setImageResource(R.drawable.btn_track_ctrl_resume); } else { // TrackRecordStatus.Stoped btnStartTrack.setVisibility(View.VISIBLE); btnPauseTrack.setVisibility(View.GONE); btnStopTrack.setVisibility(View.GONE); } } public void setTrackRecordInfo(@Nullable TrackRecordInfo trackRecordInfo) { this.trackRecordInfo = trackRecordInfo; refreshView(); } public interface TrackCtrlViewListener{ /** * 用户点击按钮 */ public void trackStatusRequest(@Nullable TrackRecordStatus newStatus); }}
Model实现:
public class TrackRecordInfo { private static final Gson gson = new Gson(); /** * 应该是保存轨迹数据库id,此demo中数据库操作不实现,暂时trackId一直为0 */ public int trackId; public TrackRecordStatus status; public TrackRecordInfo(int trackId, TrackRecordStatus status) { this.trackId = trackId; this.status = status; } @NonNull public static TrackRecordInfo loadTrackRecordInfo(@NonNull Context context){ String pref = SpUtil.getString(context, SpUtil.KEY_TRACK_RECORD_INFO, ""); if(!TextUtils.isEmpty(pref)){ return gson.fromJson(pref, TrackRecordInfo.class); } return null; } public static void changeTrackRecordInfo(@NonNull Context context, @Nullable TrackRecordInfo info){ SpUtil.saveString(context, SpUtil.KEY_TRACK_RECORD_INFO, info == null ? "" : gson.toJson(info)); //model通过消息总线,通知View刷新 EventBus.getDefault().post(new EventTrackRecordInfoChanged(info)); }}
Controller实现:
public class MainActivity extends ActionBarActivity implements TrackCtrlView.TrackCtrlViewListener{ private TrackCtrlView trackCtrlView; private TrackRecordInfo trackRecordInfo; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); trackCtrlView = new TrackCtrlView(this, this); EventBus.getDefault().register(this); trackRecordInfo = TrackRecordInfo.loadTrackRecordInfo(this); trackCtrlView.setTrackRecordInfo(trackRecordInfo); } @Override protected void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); } @Override public void trackStatusRequest(@Nullable TrackRecordStatus newStatus) { if(newStatus == TrackRecordStatus.Recording){ int trackId = 0; //在数据库创建一条轨迹,并获取到数据库id trackRecordInfo = new TrackRecordInfo(trackId, TrackRecordStatus.Recording); }else if (newStatus == TrackRecordStatus.Paused) { if(trackRecordInfo != null){ trackRecordInfo.status = newStatus; } } else { trackRecordInfo = null; } TrackRecordInfo.changeTrackRecordInfo(this, trackRecordInfo); } public void onEventMainThread(EventTrackRecordInfoChanged event){ trackRecordInfo = event.info; trackCtrlView.setTrackRecordInfo(trackRecordInfo); }}
最后总结下3者之间的关系:
Android中,model通知view改变,可以通过消息总线实现。
二:MVP 模式将 Controller 改名为 Presenter,同时改变了通信方向。
1. 各部分之间的通信,都是双向的。
2. View 与 Model 不发生联系,都通过 Presenter 传递。
3. View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。
至此为止,通过 MVP+RxJava 的组合,我们已经构建出一个比较灵活的 Android 项目框架,总共分成了四部分:View 层,Presenter 层,Model 业务层,Data 数据持久化层。这个框架的优点大概有以下几点:
- 每层各自独立,通过接口通信
- 实现与接口分离,不同场景(正式,测试)可以挂载不同的实现,方便测试和开发写假数据
- 所有的业务逻辑都在非UI线程中进行,最大限度减少IO操作对UI的影响
- 使用 RxJava 可以将复杂的调用进行链式组合,解决多重回调嵌套问题
三:MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。
唯一的区别是,它采用双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之亦然。Angular和 Ember 都采用这种模式。
- MVC->MVP->MVVM(未完)
- MVC,MVP,MVVM模式
- MVC MVP MVVM综合
- MVC,MVP,MVVM
- MVC MVP MVVM
- MVC、MVP 和 MVVM
- MVC MVP MVVM
- 前端MVC&MVP&MVVM
- mvc mvp mvvm
- MVC, MVP与MVVM
- MVC、MVP、MVVM
- MVC,MVP 和 MVVM
- MVC,MVP 和 MVVM
- MVC、MVP和MVVM
- MVC MVP MVVM
- MVC,MVP,MVVM
- MVC、MVP、MVVM
- mvc.mvp,mvvm
- spring mvc 接受对象数组
- inetd源代码分析之调试信息对应的源代码
- linux字符驱动之查询按键
- 学渣到CTO的心路历程
- 结构型模式之装饰模式
- mvc mvp mvvm
- 汉字转拼音控制器
- 设计模式也可以这么简单
- 洛谷2704 炮兵阵地
- C#解析JSON字符串总结
- 读懂正则表达式就这么简单
- K-means聚类分析与python实现
- jQuery的load方法设计动态加载及解决被加载页面js
- http://blog.csdn.net/u013142781