博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android应用程序MVC框架实例分析
阅读量:5291 次
发布时间:2019-06-14

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

问题提出:如何优雅地分离出应用程序的状态、用户交互和数据表现?如何通过框架体现工程的高性能、高灵活性、高响应性?

MVC定义:model、view、controller三者的有机组合,分别表示:模型、视图和控制。

这个模式认为:程序不论简单还是复杂,从结构上来看,都可以分为三个层次。

下图展示了MVC程序框架在Android应用程序中的使用,以及各个层次使用哪些组件担当:

1)最上面一层,是直接面向于最终用户的“视图层”(View)。它是提供给用户的操作界面,是程序的外壳。界面就是各种UI组件(XML布局或者Java自定义控件对象)。只负责展示数据,同时接收控制器传过来的结果。

2)最底下的一层,是核心的“数据层”(Model),也就是程序需要操作的数据或信息(系统中的业务逻辑部分)。通常是数据库SQLite、网络请求的JSON、本地XML或者Java对象数据。它代表了一些实体类,用来描述业务逻辑怎么组合,同时也为数据定义业务规则;

3)中间的一层,就是“控制层”(controller),负责根据用户从“视图层”输入的指令,选取“数据层”中的数据,然后对其进行相应的操作,产生最终的结果(可以分派用户的请求并选择恰当的视图以用于显示,同时也可以解释用户的数据并将它们映射为模型层可执行的操作)。控制器是与应用程序相关联的动作集合,负责处理待响应的请求。通过界面响应用户输入,通过模型层处理数据,最后返回结果给界面。控制器扮演着模型和界面的粘合剂角色。

抽象一点,上述模型可以抽象为下述结果:

展示了从Activity接收用于点击输入,控制器响应用户输入并发起Internet请求数据(网络请求),响应结果经过模型层转换,最后控制器取到模型层数据并通知界面进行刷新。

更加简化的MVC模型如下:

或者是下述结果:

在Android中,View和Model也是有关联的,从而抽象为下述图:

上述的三个层次是紧密联系,且是相互独立的,每一层的变化不影响其他层次。每一层都对外提供接口,供上面一层调用。软件因而实现模块化,修改外观或者变更数据都不用修改其他层次,大大方便了维护和升级。

一个逻辑模型可以对于多种视图模型,比如一批统计数据可以分别用柱状图、饼状图来显示结果;一种视图模型也可以对应多种逻辑模型。使用MVC的目的就是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式,而Controller存在的目的则是确保M改变,V应该同步更新。

使用计算器这个例子作为实例进行分析:外部的按钮和上面的显示条,就是“视图层”;需要运算的数字就是“数据层”;执行加减乘除的内部运算步骤就是“控制层”。每一层执行不同的功能,整个程序的结构很清晰。

MVC的好处在于:从用户的角度出发,用户可以根据自己的需求,选择自己合适浏览数据的方式。比如说,对于一篇在线文档,用户可以选择以HTML网页的方式阅读,也可以选择以pdf的方式阅读。从开发者的角度来看,MVC把应用程序的逻辑层与界面完全分开。

Android应用程序中,MVC框架是如何实现的?都充当什么角色?

1. View接受用户的交互请求;

2. View将请求转交给Controller;

3. Controller(用户做的动作比如:update数据,删除指定名字的学生等等)操作Model进行数据更新(根据用户指示,执行底层的数据动作等等);

4. 数据更新之后,Model通知View数据变化;

5. View显示更新之后的数据;

M层适合做一些业务逻辑处理,比如数据库存取操作、网络操作、复杂的算法等耗时操作;

V层显示数据部分,XML布局可以视为是V层,显示Model层的数据结果;

C层适合使用Activity担当,Android中Activity用于处理用户交互问题(发起业务请求),读取用户输入(等待业务处理结果),响应用户点击等等事件。

MainActivity.java代码如下:

package com.demo.controller;		import static com.demo.controller.ControllerProtocol.C_DATA;	import static com.demo.controller.ControllerProtocol.C_QUIT;	import static com.demo.controller.ControllerProtocol.C_UPDATE_FINISHED;	import static com.demo.controller.ControllerProtocol.C_UPDATE_STARTED;	import static com.demo.controller.ControllerProtocol.V_REQUEST_DATA;	import static com.demo.controller.ControllerProtocol.V_REQUEST_QUIT;	import static com.demo.controller.ControllerProtocol.V_REQUEST_UPDATE;		import android.app.Activity;	import android.os.Bundle;	import android.os.Handler;	import android.os.Handler.Callback;	import android.os.Message;	import android.util.Log;	import android.view.View;	import android.widget.ProgressBar;	import android.widget.TextView;		import com.demo.R;	import com.demo.model.Model;	import com.demo.model.ModelData;	import com.demo.utils.LogUtil;		public class MvcActivity extends Activity implements Callback,	        View.OnClickListener {	    private static final String TAG = MvcActivity.class.getSimpleName();		    private Controller controller;		    @Override	    public void onCreate(Bundle savedInstanceState) {	        super.onCreate(savedInstanceState);	        setContentView(R.layout.main);		        findViewById(R.id.update).setOnClickListener(this);	        findViewById(R.id.quit).setOnClickListener(this);		        // 初始化层次结构中的交互	        controller = new Controller(new Model());	        // 使用MvcActivity所在的主线程初始化outBox中的Handler	        controller.addOutboxHandler(new Handler(MvcActivity.this));	        // Controller层发送请求数据的Message	        controller.getInboxHandler().sendEmptyMessage(V_REQUEST_DATA);	    }		    @Override	    public void onClick(View v) {	        // 接收用户输入	        switch (v.getId()) {	            case R.id.update:	                LogUtil.d(TAG, "User click input: R.id.update");	                // 接收用户输入并得到Controller层响应,Controller层发送请求数据的Message	                controller.getInboxHandler().sendEmptyMessage(V_REQUEST_UPDATE);	                break;	            case R.id.quit:	                LogUtil.d(TAG, "User click input: R.id.quit");	                // 接收用户输入并得到Controller层响应,Controller层发送请求数据的Message	                controller.getInboxHandler().sendEmptyMessage(V_REQUEST_QUIT);	                break;	        }	    }		    @Override	    public boolean handleMessage(Message msg) {	        Log.d(TAG, "Received message: " + msg);		        switch (msg.what) {	            case C_QUIT:	                // 接收Controller层输入,准备退出应用	                onQuit();	                return true;	            case C_DATA:	                // 将数据显示到View层	                onData((ModelData) msg.obj);	                return true;	            case C_UPDATE_STARTED:	                // (状态)正在后台请求数据	                onUpdateStarted();	                return true;	            case C_UPDATE_FINISHED:	                // (状态)后台请求数据结束,准备显示	                onUpdateFinished();	                return true;	        }	        return false;	    }		    @Override	    protected void onDestroy() {	        try {	            controller.dispose();	        } catch (Throwable t) {	            LogUtil.d(TAG, "Failed to destroy the controller");	        }		        super.onDestroy();	    }		    /**	     * 
<功能描述>
Controller层做出update响应,更新View层 * * @return void [返回类型说明] */ private void onQuit() { LogUtil.d(TAG, "Activity quitting"); finish(); } /** *
<功能描述>
从Controller层传递过来的Message,表明获取到返回的数据,更新View * * @param data [参数说明] * @return void [返回类型说明] */ private void onData(ModelData data) { LogUtil.d(TAG, "onData::running..."); TextView dataView = (TextView) findViewById(R.id.data_view); dataView.setText("The answer is " + data.getAnswer()); } /** *
<功能描述>
开始Update数据显示ProgressBar * * @return void [返回类型说明] */ private void onUpdateStarted() { LogUtil.d(TAG, "onUpdateStarted::running..."); ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar); progressBar.setVisibility(View.VISIBLE); } /** *
<功能描述>
Update数据过程结束后,ProgressBar消失,显示数据 * * @return void [返回类型说明] */ private void onUpdateFinished() { LogUtil.d(TAG, "onUpdateFinished::running..."); ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar); progressBar.setVisibility(View.GONE); controller.getInboxHandler().sendEmptyMessage(V_REQUEST_DATA); } }

Controller.java代码如下:

package com.demo.controller;		import static com.demo.controller.ControllerProtocol.C_QUIT;		import android.os.Handler;	import android.os.HandlerThread;	import android.os.Message;		import com.demo.model.Model;	import com.demo.utils.LogUtil;		import java.util.ArrayList;	import java.util.List;		public class Controller {	    private static final String TAG = Controller.class.getSimpleName();		    private final Model model;		    // 使用HandlerThread、Handler、Message机制实现不同层的消息通信	    // inBox:用于接收从View层发送的Message	    private final HandlerThread inboxHandlerThread;	    private final Handler inboxHandler;	    // outBox:用于Controller给View发送Message	    private final List
outboxHandlers = new ArrayList
(); // 将消息处理委托给ControllerState,不在Controller中处理Message private ControllerState state; /** *
<默认构造函数>
Controller层初始化 */ public Controller(Model model) { this.model = model; // Handler就存在于该Thread子线程(也就是工作线程)中 inboxHandlerThread = new HandlerThread("Controller Inbox"); inboxHandlerThread.start(); // HandlerThread的getLooper()获取到Handler实例 inboxHandler = new Handler(inboxHandlerThread.getLooper()) { @Override public void handleMessage(Message msg) { Controller.this.handleMessage(msg); } }; // 初始化ControllerState,准备接受Message this.state = new ReadyState(this); } // 处理从View层传递过来的Message private void handleMessage(Message msg) { LogUtil.d(TAG, "handleMessage::Received message...msg.what=" + msg.what); // 把消息处理委托给它的 ControllerState if (!state.handleMessage(msg)) { LogUtil.d(TAG, "Unknown message: " + msg); } } /** *
<功能描述>
inboxHandlerThread退出 * * @return void [返回类型说明] */ public final void dispose() { inboxHandlerThread.getLooper().quit(); } /** *
<功能描述>
获取inBox的Handler实例,并返回该实例 * * @return [参数说明] * @return Handler [返回类型说明] */ public final Handler getInboxHandler() { return inboxHandler; } /** *
<功能描述>
增加Handler到outBox中;outBox用于Controller传送Message到View层 * * @param handler [参数说明] * @return void [返回类型说明] */ public final void addOutboxHandler(Handler handler) { outboxHandlers.add(handler); } /** *
<功能描述>
从outBox移除Handler * * @param handler [参数说明] * @return void [返回类型说明] */ public final void removeOutboxHandler(Handler handler) { outboxHandlers.remove(handler); } /** *
<功能描述>
更新Controller的状态,ReadyState和UpdatingState之间的切换 * * @param newState [参数说明] * @return void [返回类型说明] */ final void changeState(ControllerState newState) { LogUtil.d(TAG, String.format("Changing state from %s to %s", state, newState)); state = newState; } /** *
<功能描述>
Controller层向View层发送Message * * @param what * @param arg1 * @param arg2 * @param obj [参数说明] * @return void [返回类型说明] */ final void notifyOutboxHandlers(int what, int arg1, int arg2, Object obj) { LogUtil.d(TAG, "notifyOutboxHandlers::running...what=" + what); if (outboxHandlers.isEmpty()) { LogUtil.d(TAG, String.format( "No outbox handler to handle outgoing message (%d)", what)); } else { for (Handler handler : outboxHandlers) { Message msg = Message.obtain(handler, what, arg1, arg2, obj); msg.sendToTarget(); } } } /** *
<功能描述>
获取到Model层 * * @return [参数说明] * @return Model [返回类型说明] */ final Model getModel() { return model; } /** *
<功能描述>
接收用户输入,准备退出应用 * * @return void [返回类型说明] */ final void quit() { notifyOutboxHandlers(C_QUIT, 0, 0, null); } }

ControllerState.java代码如下:

package com.demo.controller;		import android.os.Message;		/**	 * 
<功能描述>
将Controller层的消息处理逻辑转交给ControllerState处理;ControllerState有两个实现类: * ReadyState和UpdatingState * * @author Administrator */ public interface ControllerState { boolean handleMessage(Message msg); }

ReadyState.java代码如下:

package com.demo.controller;		import android.os.Message;		import com.demo.utils.LogUtil;		import static com.demo.controller.ControllerProtocol.*;		/**	 * 
<功能描述>
数据更新的状态之一:准备阶段,最前面的状态 * * @author Administrator */ final class ReadyState implements ControllerState { private static final String TAG = ReadyState.class.getSimpleName(); private final Controller controller; public ReadyState(Controller controller) { this.controller = controller; } @Override public final boolean handleMessage(Message msg) { LogUtil.d(TAG, "handleMessage::running...msg.what=" + msg.what); switch (msg.what) { case V_REQUEST_QUIT: // 从View层获取到的Quite消息 onRequestQuit(); return true; case V_REQUEST_UPDATE: // 从View层获取到的Update的消息 onRequestUpdate(); return true; case V_REQUEST_DATA: // 从View层获取到的更新数据的消息 onRequestData(); return true; } return false; } /** *
<功能描述>
请求数据 * * @return void [返回类型说明] */ private void onRequestData() { LogUtil.d(TAG, "onRequestData::running..."); controller.notifyOutboxHandlers(C_DATA, 0, 0, controller.getModel() .getData()); } /** *
<功能描述>
请求更新数据,并更改Controller的状态 * * @return void [返回类型说明] */ private void onRequestUpdate() { LogUtil.d(TAG, "onRequestUpdate::running..."); // 状态返回给Controller层,并将状态改变为UpdatingState controller.changeState(new UpdatingState(controller)); } private void onRequestQuit() { LogUtil.d(TAG, "onRequestQuit::running..."); controller.quit(); } }

UpdatingState.java代码如下:

package com.demo.controller;		import static com.demo.controller.ControllerProtocol.C_UPDATE_FINISHED;	import static com.demo.controller.ControllerProtocol.C_UPDATE_STARTED;	import static com.demo.controller.ControllerProtocol.V_REQUEST_QUIT;		import android.os.Message;		import com.demo.utils.LogUtil;		/**	 * 
<功能描述>
数据更新的状态之一:正在更新阶段 * * @author Administrator */ final class UpdatingState implements ControllerState { private static final String TAG = UpdatingState.class.getSimpleName(); private final Controller controller; private final Thread updateThread; public UpdatingState(Controller controller) { this.controller = controller; // 新建一个Thread工作线程 updateThread = new Thread("Model Update") { @Override public void run() { Controller controller = UpdatingState.this.controller; try { // 在工作线程中执行数据请求(抽象为相对耗时的操作),可为其他:数据库操作 controller.getModel().updateData(); } catch (Throwable t) { LogUtil.d(TAG, "Error in the update thread"); } finally { // controller.getModel().updateData()执行完后,反馈数据给Controller层 notifyControllerOfCompletion(); } } }; updateThread.start(); // Controller层向View层发送Message,开始更新数据 controller.notifyOutboxHandlers(C_UPDATE_STARTED, 0, 0, null); } @Override public boolean handleMessage(Message msg) { LogUtil.d(TAG, "handleMessage::msg.what=" + msg.what); switch (msg.what) { case V_REQUEST_QUIT: onRequestQuit(); return true; } return false; } /** *
<功能描述>
数据获取到后,最终会反馈给Controller层 * * @return void [返回类型说明] */ private void notifyControllerOfCompletion() { LogUtil.d(TAG, "notifyControllerOfCompletion::starting..."); controller.getInboxHandler().post(new Runnable() { @Override public void run() { // 将状态改变为ReadyState controller.changeState(new ReadyState(controller)); // 并通知结束更新 controller.notifyOutboxHandlers(C_UPDATE_FINISHED, 0, 0, null); } }); } private void onRequestQuit() { LogUtil.d(TAG, "onRequestQuit::starting..."); updateThread.interrupt(); controller.quit(); } }

ControllerProtocal.java代码如下:

package com.demo.controller;		public interface ControllerProtocol {	    // 从View层传递的Message	    int V_REQUEST_QUIT = 101;	    int V_REQUEST_UPDATE = 102;	    int V_REQUEST_DATA = 103;		    // 从Controller层传递的Message	    int C_QUIT = 201;	    int C_UPDATE_STARTED = 202;	    int C_UPDATE_FINISHED = 203;	    int C_DATA = 204; // obj = (ModelData) data	}

Model.java代码如下:

package com.demo.model;		import java.util.ArrayList;	import java.util.List;	import java.util.Random;		import android.os.SystemClock;		import com.demo.utils.LogUtil;		/**	 * 
<功能描述>
专指Model层;使用ThreadSafe指示是线程安全的 * * @author Administrator */ public class Model { private static final String TAG = Model.class.getSimpleName(); public interface Listener { void onModelStateUpdated(Model model); } // Model模型中包含有ModelData private ModelData data = new ModelData(0); private final List
listeners = new ArrayList
(); public Model() { LogUtil.d(TAG, "Model constructer.."); } public final ModelData getData() { synchronized (this) { return data; } } /** *
<功能描述>
更新数据 * * @return void [返回类型说明] */ public final void updateData() { // 可能是请求服务器数据,执行繁重的计算 SystemClock.sleep(3000); ModelData newData = new ModelData(new Random().nextInt(10) + 1); synchronized (this) { data = newData; } synchronized (listeners) { for (Listener listener : listeners) { listener.onModelStateUpdated(this); } } } /** *
<功能描述>
增加监听器 * * @param listener [参数说明] * @return void [返回类型说明] */ public final void addListener(Listener listener) { synchronized (listeners) { listeners.add(listener); } } /** *
<功能描述>
移除监听器 * * @param listener [参数说明] * @return void [返回类型说明] */ public final void removeListener(Listener listener) { synchronized (listeners) { listeners.remove(listener); } } }

ModelData.java代码如下:

package com.demo.model;		import com.demo.utils.LogUtil;		import java.io.Serializable;		/**	 * 
<功能描述>
Model层中的数据,指示数据层的状态;Immutable指示是不变的 * * @author Administrator */ public final class ModelData implements Serializable { private static final String TAG = ModelData.class.getSimpleName(); private static final long serialVersionUID = 1L; private final int answer; public ModelData(int answer) { LogUtil.d(TAG, "ModelData::answer=" + answer); this.answer = answer; } public final int getAnswer() { LogUtil.d(TAG, "getAnswer::answer=" + answer); return answer; } }

View代码如下:

更加详细的MPV模型解析:

转载于:https://www.cnblogs.com/CVstyle/p/6389990.html

你可能感兴趣的文章
使用Chrome(PC)调试移动设备上的网页
查看>>
UI基础--手写代码实现汤姆猫动画
查看>>
NSDictionary的几种遍历方法
查看>>
内核映像的形成 —— KBuild体系
查看>>
Python+pytesseract+Tesseract-OCR图片文字识别(只适合新手)
查看>>
使用gitbash来链接mysql
查看>>
docker镜像管理基础
查看>>
黑盒测试和百合测试的优缺点对比
查看>>
SecureCRT的使用方法和技巧(详细使用教程)
查看>>
装饰者模式
查看>>
右侧导航栏(动态添加数据到list)
查看>>
用Nginx+Lua(OpenResty)开发高性能Web应用
查看>>
gulp 入门---使用gulp压缩JS
查看>>
81、iOS本地推送与远程推送详解
查看>>
Sharepoint online 如何使用asp.net开发项目!!!
查看>>
C#基础_注释和VS常用快捷键(一)
查看>>
http协议
查看>>
为什么CPU时钟频率在过去5年里没有增加?
查看>>
动态调用webservice
查看>>
2017-05-18
查看>>