博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
简述MVC框架模式以及在你(Android)项目中的应用
阅读量:4567 次
发布时间:2019-06-08

本文共 6501 字,大约阅读时间需要 21 分钟。

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

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

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

 

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

  前端之Android入门(3):MVC模式:

  
  
  

  The Activity Revisited:

  

  谈谈UI架构设计的演化:

  

  MVC,MVP 和 MVVM 的图示:

  

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

  

 

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

 

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

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

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

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

 

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

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

  

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

  demo源码地址:  

  

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

 

转载于:https://www.cnblogs.com/John-Chen/p/4458823.html

你可能感兴趣的文章
2、文件夹
查看>>
11、求二进制中1的个数
查看>>
【nodejs】让nodejs像后端mvc框架(asp.net mvc)一样处理请求--请求处理结果适配篇(7/8)...
查看>>
MySQL 删除数据库
查看>>
JavaScript 字符串(String) 对象
查看>>
How to use VisualSVN Server and TortoiseSVN to host your codes and control your codes' version
查看>>
微信小程序picker组件 - 省市二级联动
查看>>
Dynamics CRM 给视图配置安全角色
查看>>
Eclipse修改已存在的SVN地址
查看>>
(转)使用 python Matplotlib 库绘图
查看>>
进程/线程切换原则
查看>>
正则表达式语法
查看>>
20165301 2017-2018-2 《Java程序设计》第四周学习总结
查看>>
Vue的简单入门
查看>>
urllib 中的异常处理
查看>>
通过SQL Server的扩展事件来跟踪SQL语句在运行时,时间都消耗到哪儿了?
查看>>
20181227 新的目标
查看>>
androidtab
查看>>
php 事件驱动 消息机制 共享内存
查看>>
剑指offer 二叉树的bfs
查看>>