第2章第4节界面MVC(上)

内容摘要

上节我们学习了简单的Android程序入门,使大家对Android开发有了初步的印象,本节我们讲解一下简单的前端架构设计。

1.MVC简介

2.坏的设计

3.稍好点的设计

4.一点设计经验

5.总结

其实架构设计无处不在,而APP开发很少涉及架构设计,因为APP的功能定位比较简单,都是在单进程下的单用户操作,很少有APP开发者设计非常复杂的多线程架构,但是这并不等于APP的开发就无需架构设计。

对于经验欠缺的APP开发者,你会发现他们设计的目录结构以及代码与代码之间的逻辑关系非常混乱,很多功能都罗列在一切,只是简单的让程序能跑起来,并不怎么关心可维护性和可持续改进的能力。

我曾经见到过这样的代码:布局文件既有xml文件来设置,也有java代码来设置的,非常混乱的掺杂在一起,导致后期维护非常苦难。你会发现对于这样的代码,接手者的第一反应是,修改还不如重写。

因此本节介绍一种简单的设计模式,MVC模式,让你的APP代码目录结构简洁,做到高内聚,低耦合。写出漂亮的代码既能够方便自己的管理和维护,又方便他人阅读和维护。

MVC简介

MVC:Model View Controller ,这里我简单说一下我的理解,Model就是数据, View就是数据的展示, Controller 是控制如何展示数据以及用户操作界面之后,怎样存储最新数据。如果有兴趣的同学,可以去网上搜索一下更详细的知识。我从网上搜了一个比较准确的图片:

我们以展示某学生的简单信息为例,假设学生信息只有4个属性:姓名,学号,年龄,年级。我们的主要工作就是展示某学生的基本信息,并支持简单的内容修改。

首先我们把流程描述一下,你就会发现,每个步骤都要有一个角色去实现

step1:我们根据学生的学号,从数据库或者网络获取关于该学生的基本信息,并存储到某个对象里面。

step2:我们需要生成或者加载一个界面来展示学生的基本信息。

step3:我们需要把step1中存储的学生信息,赋值给展示界面的各个控件,当用户修改这些信息的时候,还需要将用户修改的数据,赋值给存储对象,并存储回数据库或者网络。

那么根据以上流程,你就会发现,step1中的功能就需要一个model这样的角色来处理,step2中的展示功能,就需要view这样的角色来处理,step3中的逻辑处理就是controller的工作。

这应该是最简单的MVC的解释了,关于MVC设计模式,并没有非常清晰的定义和概念的描述,总的原则就是分离数据,展示,处理逻辑这三部分,让代码清晰可读,容易理解。接下来我将用两个例子来展示,好的设计和一锅粥式的代码实现,有什么区别。

坏的设计

我们在上一节中的Hello World基础上,增加一个新的Activity ,并从MainActivity跳转到新界面,这个新建的Activity将为大家展示一个不好的设计代码。

首先新建一个basic activity。

点击finish, 然后我们在Hello Word的MainActivity里面增加一个跳转到我们示例的按钮,并增加响应代码,如下:

public void jumpToBad(View view){

Intent intent = new Intent(this, MVCBadActivity.class);

intent.putExtra("name", "李四");

intent.putExtra("idCard", "wx001");

intent.putExtra("age", 20);

intent.putExtra("grade", 2);

startActivity(intent);

}

我们在跳转到新的界面之前,将数据传输到新的界面,在生产环境下,一般都是从本地数据库获取或者从网络获取,然后再在新界面展示。

接下来我们就是要创建一些页面元素来展现我们得到的数据。这是本节要讲解的重点,我们先看一个不好的例子,一个Activity这样的Controller如何把学生信息这个Model展现在Textview,EditText这些android的View上的。先看代码:

public class MVCBadActivity extends AppCompatActivity {

String stu_name, stu_idCard;

int stu_age, stu_grade;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

Intent intent = getIntent();

stu_name = intent.getStringExtra("name");

stu_idCard = intent.getStringExtra("idCard");

stu_age = intent.getIntExtra("age", 18);

stu_grade = intent.getIntExtra("grade", 1);

......

首先定义私有成员变量,接收从前一个界面传输过来的数据,这部分逻辑就是Model模块的角色应该承担的任务。

RelativeLayout layout = new RelativeLayout(this);

RelativeLayout.LayoutParams layoutParams = new     RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);

layout.setLayoutParams(layoutParams);

然后创建一个相对布局,用来展示这些数据,创建布局,以及设置布局的大小和相对位置,这些工作是Controller这个角色来完成的,而创作出来的对象就是View这个角色,View的任务就是作为一个手机操作系统可以理解并能够显示的对象,用来展示Controller赋予他的内容 。

TextView label_name = new TextView(this);

label_name.setId(1);

label_name.setText("学生姓名:");

RelativeLayout.LayoutParams params1 = new RelativeLayout.LayoutParams(

RelativeLayout.LayoutParams.WRAP_CONTENT,

RelativeLayout.LayoutParams.WRAP_CONTENT);

EditText text_name = new EditText(this);

text_name.setId(2);    text_name.setEms(5);

text_name.setInputType(InputType.TYPE_TEXT_VARIATION_PERSON_NAME);

text_name.setText(stu_name);

RelativeLayout.LayoutParams params2 = new     RelativeLayout.LayoutParams(300,                RelativeLayout.LayoutParams.WRAP_CONTENT);

params2.addRule(RelativeLayout.RIGHT_OF, label_name.getId());

params1.addRule(RelativeLayout.ALIGN_BOTTOM, text_name.getId());

params2.leftMargin = 180;

layout.addView(label_name, params1);

layout.addView(text_name, params2);

添加一个标签,提示当前数据表示的是学生姓名。然后添加一个可以编辑的控件,用来展示学生姓名给用户并且可以接受用户对学生姓名的修改。

这里需要注意的是需要通过代码来设置两个控件的大小,距离,以及相对位置等信息,最后通过addview函数将两个控件放到整个页面的相对布局中。

其它三个控件的设置与此类似,不再赘述。这里所用到的EditText和TextView控件,都是继承自android的android.view.View这个类,通过android studio的查看源码的方式,可以跟踪到这些控件的父类,此处的View类的命名,很好地诠释了MVC设计中的View角色应该承担的工作。

提示:在oncreate函数的最后要调用setContentView(layout);

所有控件添加完成之后,效果是这样的:

这里需要再深入讲解一下的是“修改”这个按钮的布局和逻辑处理:

RelativeLayout.LayoutParams params9 = new RelativeLayout.LayoutParams(300,            RelativeLayout.LayoutParams.WRAP_CONTENT);

params9.topMargin = 200;

params9.leftMargin = 100;

params9.addRule(RelativeLayout.BELOW, label_grade.getId());

Button btn_ok = new Button(this);

btn_ok.setText("修改");

btn_ok.setId(9);

btn_ok.setOnClickListener(new View.OnClickListener(){

@Override

public void onClick(View v) {

stu_name = text_name.getText().toString();

stu_idCard = text_idCard.getText().toString();

stu_age = Integer.valueOf(text_age.getText().toString());

stu_grade = Integer.valueOf(text_grade.getText().toString());

//调用数据库存储或者网络存储

Toast.makeText(MVCBadActivity.this, "处理完成",

Toast.LENGTH_SHORT).show();

finish();

}

});

代码前半部分是布局设置,与其它控件的设置相似,重点是按钮的响应代码。当用户修改了基本信息的时候,我们从这些View获取数据并把数据复制给对应的私有成员变量。这个过程就是在Controller的控制下,将View的数据赋值给Model角色。

还有一点需要说明的就是 finish()函数的调用,这个动作是将当前Activity从堆栈中弹出并且释放内存资源,此知识点在本章中第二节中详细的介绍过,不理解的同学可以温习一下。

至此已经将这个demo讲解完毕,通篇代码设计的缺陷也比较明显,数据的加载赋值,View的创建和位置的设置,数据反馈给Model的代码逻辑,控件的响应函数,全部融合在Controller这一个角色里面。

当工程比较简单的情况下,尚且可以维护,但是如果代码逻辑变得复杂,数据展示内容变多,各种动画效果和图片都融合在一起的时候,这样的代码将会变得非常复杂和冗长。

但是所有的事情有利有弊,这段代码的为数不多的优势就是,方便初学者学习和理解代码逻辑,特别是在我们讲解MVC模式的时候,通过一个函数就可以直观看到Controller如何操作Model和View的,以及他们之间如何交互。(未完待续)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容