标题是阿里电话面试的问题,一直以为自己很清楚MVC模式,结果被问到时,居然没法将MVC和Android中各个组件对应起来,所以,面试肯定挂了,不过面试也是学习的一种方式,可以知道大公司看中什么,以及自己还有哪些知识漏洞,例如这次面试就学到了很多东西。

  大家可以在看下面的内容之前,也想想能否把MVC及与Android各个组件的对应关系讲清楚,看是否还有和我一样对MVC一知半解的。

   如果写的有问题的地方,欢迎讨论。转载请注明出处:http://www.cnblogs.com/John-Chen/p/4458823.html

  学习中读了很多别人总结的文章,有几篇不错,推荐给大家:  

  前端之Android入门(3):MVC模式:
  http://isux.tencent.com/learn-android-from-zero-session3.html
  http://isux.tencent.com/learn-android-from-zero-session4.html
  http://isux.tencent.com/learn-android-from-zero-session5-html.html

  The Activity Revisited:
  http://www.therealjoshua.com/2012/07/android-architecture-part-10-the-activity-revisited/

  谈谈UI架构设计的演化:
  http://www.cnblogs.com/winter-cn/p/4285171.html

  MVC,MVP 和 MVVM 的图示:
  http://www.ruanyifeng.com/blog/2015/02/mvcmvp_mvvm.html

  关于另一种框架模式MVP的实践:

  http://www.imooc.com/wenda/detail/216700

  重新学习思考之后,再看自己项目中的某些实现,其实很多地方已经是遵循MVC的思想在实现,只是在设计和实现时,没提升到框架模式,只是根据以前的经验,以及一些基本的设计思想在做,所以被问到MVC模式时,也没想到项目中有用到的地方。我觉得不管了不了解什么框架模式以及设计模式,最主要的是得想办法做到解耦以及提升应用的稳定性。

  首先说下我现在认识的MVC与Android的各个组件的对应关系:

  View:自定义View或ViewGroup,负责将用户的请求通知Controller,并根据model更新界面;

  Controller:Activity或者Fragment,接收用户请求并更新model;

  Model:数据模型,负责数据处理相关的逻辑,封装应用程序状态,响应状态查询,通知View改变,对应Android中的datebase、SharePreference等。

  下面以我做的项目中的一个模块来详细介绍Android中的MVC框架模式:

  项目中有一个记录轨迹的功能,记录有几种状态:记录、暂停、停止:

  

  接下来我把轨迹控制部分的逻辑提取出来,做了一个简单地demo,

  demo源码地址:https://github.com/John-Chen/BlogSamples/tree/master/MVCDemo  

  

  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改变,可以通过消息总线实现。

简述MVC框架模式以及在你(Android)项目中的应用的更多相关文章

  1. MVC框架模式技术实例(用到隐藏帧、json、仿Ajax、Dom4j、jstl、el等)

    前言: 刚刚学完了MVC,根据自己的感悟和理解写了一个小项目. 完全按照MVC模式,后面有一个MVC的理解示意图. 用MVC模式重新完成了联系人的管理系统: 用户需求: 多用户系统,提供用户注册.登录 ...

  2. MVC框架模式和Javaweb经典三层架构

    一.MVC设计模式 1.MVC的概念 首先我们需要知道MVC模式并不是javaweb项目中独有的,MVC是一种软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(Vie ...

  3. 通过Struts了解MVC框架,兼说如何在面试中利用Struts证明自己

    虽然目前Struts MVC框架不怎么用了,但它确是个能帮助大家很好地入门Web MVC框架,而且,一些历史项目可能还用Struts,反正技多不压身,大家如果能在面试中通过项目证明自己Struts这块 ...

  4. 对Android项目中的文件夹进行解释

    对Android项目中的文件夹进行解释: · src:里面存放的是Activity程序,或者是以后的其他组件,在此文件夹之中建立类的时候一定要注意,包名称不能是一级. · gen:此文件夹中的内容是自 ...

  5. Android项目中如何用好构建神器Gradle?(转)

    最近在忙团队并行开发的事情,主要是将各个团队的代码分库,一方面可以降低耦合,为后面模块插件化做铺垫,另一方面采用二进制编译,可以加快编译速度.分库遇到了一些问题,很多都要通过Gradle脚本解决,所以 ...

  6. android项目中配置NDK自动编译生成so文件

    1 下载ndk开发包   2 在android 项目中配置编译器(以HelloJni项目为例)  2.1 创建builer  (a)Project->Properties->Builder ...

  7. Android 项目中文件夹的说明与作用(转)

    (转自:http://blog.csdn.net/goodshot/article/details/11529731) Android 项目中文件夹的作用 1. src:存放所有的*.java源程序. ...

  8. android XMl 解析神奇xstream 一: 解析android项目中 asset 文件夹 下的 aa.xml 文件

    简介 XStream 是一个开源项目,一套简单实用的类库,用于序列化对象与 XML 对象之间的相互转换. 将 XML 文件内容解析为一个对象或将一个对象序列化为 XML 文件. 1.下载工具 xstr ...

  9. android项目中如何加载已有so库 <转>

    1,在项目根目录下建立文件夹libs/armeabi文件夹 2,将so库放入 libs/armeabi文件夹 注意事项: 1,如果采用静态注册的方式请注意C文件中严格按照命名规则 Java_packa ...

随机推荐

  1. freemarker:简介

    Apache FreeMarker模板引擎:Java库来生成文本输出(HTML网页,电子邮件,配置文件,源代码,等等)基于模板和变化的数据.模板都写在FreeMarker模板语言(FTL),这是一个简 ...

  2. java一点小的知识点

    1.在dos底下编译运行java文件时,若有包名,需要建立包名对应的文件夹,然后编译的时候写出包名:java.mypack.PackageDemo 2.代码中有包名的时候,自动创建文件夹并编译的方法: ...

  3. java 四舍五入保留小数

    // 方式一: double f = 3.1516; BigDecimal b = new BigDecimal(f); double f1 = b.setScale(2, BigDecimal.RO ...

  4. redis持久化机制

    redis持久化 redis的数据存在内存中,所以存取性能好.但是存在内存中的数据存在一个问题,一旦机器重启,内存数据消失.为了解决这个问题,redis支持持久化.持久化就是为了解决内存数据丢失时恢复 ...

  5. Guava学习笔记:Ordering犀利的比较器

    Ordering是Guava类库提供的一个犀利强大的比较器工具,Guava的Ordering和JDK Comparator相比功能更强.它非常容易扩展,可以轻松构造复杂的comparator,然后用在 ...

  6. Mac OS Git 安装

    一.Git是一个分布式的代码版本管理工具.类似的常用工具还有SVN,CVS.最大的特点也是优点在于提供分布式的代码管理 1.分支代码只有一份! 使用过svn的童鞋想必都知道,当我们要开发一个新功能或者 ...

  7. JavaScript基础------入门基础

    JavaScript他是一种描述性语言,使用JavaScript就是为了能和网页有更好的交互,下面切入主题进行讲解. 一.JavaScript 1.什么是JavaScript JavaScript是一 ...

  8. java 字符串zlib压缩/解压

    今天在测公司的中间件时发现,增加netty自带的zlib codec压缩处理后,就报decompress failed, invalid head之类的异常.后来发现,直接用bytebuf处理报文体是 ...

  9. 05Mybatis_入门程序——根据id查询用户

    这篇文章我们来做一个入门的案例: 建表: /* SQLyog v10.2 MySQL - 5.1.72-community : Database - mybatis ***************** ...

  10. 以【猫叫、老鼠跑、主人醒】为例子,使用 javascript 来实现 观察者模式 (有在线演示)

    “猫叫.老鼠跑.主人醒”是一个很古老的话题了,大家也都有各自的想法和解决方案.我也是看了很多,一开始的时候是相当的迷糊,这个怎么就是面试题了?考的是啥呀,和编程有关系吗?又是猫又是老鼠的,晕死了.后来 ...