MVC模式是我接触的第一种框架,这一框架对项目分块的很清晰。将项目分解为Model-View-Controller,对于一个Android项目来说,这样的模块划分方式还是比较方便开发的(至少我用在当时的项目确实还行)。请注意,MVC并不是一种设计模式,之前的标题有所误导,现在已经修改。
将代表显示的部分划分至View,将代表数据实体的部分划分至Model,将代表数据处理的部分划分至Controller,这样划分之后整个项目的结构也就清晰了很多。
首先,我希望能分别介绍一下MVC的三部分内容各自的属性和特点,这样应该能够更好的整体理解MVC这一框架。
Model
Model部分,也就是模型部分,这一部分将需要在View中显示的数据整合为一个实体,可以视为View显示内容的实体对象。
举个简单的例子:
一个TextView中需要显示一个人的姓名和年龄,那么对应这一个View需要的数据,可以定义一个Person类,其中包含name和age属性。
//一个简单的Model,定义了View中显示内容模型
class Person{
private String name;
private int age;
/***********/
geter...
setter...
/***********/
}
Model中定义的属性部分是由View的现实需要决定的,当然也并不是绝对,Model中的属性更多根据获取的数据来进行定义。
同样举个例子:
依照获取的数据,一个人拥有基本的属性为姓名、年龄、性别、身高、体重。那么定义一个Model可以将所有数据包含的属性都进行整合。在不同的View进行显示时都能够使用这一Model。
//包含了所有数据内容的Model,能够适用于多个View
class Person{
private String name;
private int age;
private String gender;
private int height;
private int weight;
/**********/
getter
setter
/**********/
}
从上面的例子可以看的出来,事实上Model部分就是数据实例定义,将各个类型的数据规整为不同的类,划分至Model中,通过这些类来进行与View之间的交互,同时通过这些类获取并保存数据。
View
view部分内容,通常称为视图部分,这一部分内容主要是用于做显示功能的,Android应用作为移动客户端上的产品,相比于数据处理,更多的是对View的开发。可以简单的将View看做视图内容,在Android方面来说,基本是xml文件的定义。
事实上Android中因为自定义控件的存在,出现了各种不同功能不同形式的View,当然本质上还是相差不远的,大部分的目的都是——显示数据,与数据交互
举个简单的例子:
//Android中的基础控件(TextView、Button)
//常用于显示数据
<TextView
android:id="@+id/tv_mvc"
android:width="warp_content"
android:height="warp_content"
text="hello mvc"/>
//常用于点击交互
<Button
android:id="@+id/bt_mvc"
android:width="warp_content"
android:height="warp_content"
text="getName"/>
以上例子省略的外部的layout,这是一个简单的View组合,包含TextView和Button两个View组件,以上的部分可以完成简单的数据显示,并且能够相应用户操作,这也就是View的主要作用。
Controller
这是View与Model之间进行交互的桥梁,而Controller的作用就是通过对View动作的响应来操作Model,在Android端来说,这些工作不可避免的要在Activity或是Fragment中来完成。这也就是之前提到的使用MVC会导致Activity/Fragment变得臃肿的主要原因。
举个例子:
"/**结合之前View和Model中的例子来看**/"
"//创建Person对象实例"
Person person = new Person();
"//Button点击监听"
bt_mvc.setOnClickListener(new OnClickListener(){
public void onClick(View v){
"//获取TextView显示的文本"
String name = tv_mvc.getText().toString();
"//存储person对象的name属性"
person.setName(name);
}
});
这是一次简单的Controller操作过程,监听View(Button)的点击事件,当Button受到用户点击时,获取View(TextView)的文本内容,将文本内容的String值赋给Model(Person)实例。通过Controller完成由View响应开始完成与Model交互的过程。
MVC框架分解
完成了MVC框架的各个部分之后,我们可以从将框架稍稍分解来观察不同部分之间是怎样进行交互的。
-
M——V
之前介绍过,Model部分与View部分是可以直接进行交互的,比较常见的交互有Adapter的形式,修改Model,通过BaseAdapter的notifyDataSetChanged()刷新View。这个类型的交互应该不难理解。 -
M——Controller/V——Controller
直接的修改,不做太多解释了。 -
V——Controller
这一部分内容常见的有控件的回调方法,通过对控件各个事件监听来完成对成View与Controller之间的交互。
框架依照这个形式搭建,将项目中的内容按照这三部分进行划分。首先项目的结构就能够比较清晰的呈现;其次在维护是也能够较快捷的找到所需要维护位置及相应的类。Android端也更便于修改项目之间的逻辑。但依照这一框架搭建项目时,非常直观的问题:Activity、Fragment中的代码量极大。View与Model之间的交互基本都会在Activity中进行,还有Controller也很难避开Activity。
MVC整体示例
Model
/*Person类,包含属性:姓名,性别,年龄,身高,体重*/
public class Person {
private String name;
private String gender;
private int age;
private int height;
private int weight;
public Person(String name, String gender, int age, int height, int weight) {
this.name = name;
this.gender = gender;
this.age = age;
this.height = height;
this.weight = weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
View
Activity的布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/et_example"
android:layout_width="0dp"
android:gravity="center_horizontal"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="name"
android:textSize="18sp"/>
<Button
android:id="@+id/bt_example"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="get"/>
</LinearLayout>
<ListView
android:id="@+id/lv_example"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
数据列表布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_lv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="name"
android:textSize="18sp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_lv_age"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="age"
android:textSize="18sp"/>
<TextView
android:id="@+id/tv_lv_gender"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="gender"
android:textSize="18sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_lv_weight"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="weight"
android:textSize="18sp"/>
<TextView
android:id="@+id/tv_lv_height"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="height"
android:textSize="18sp"/>
</LinearLayout>
</LinearLayout>
Controller
Button bt_example = (Button) findViewById(R.id.bt_example);
assert bt_example != null;
bt_example.setOnClickListener(this);
//通过用户点击,获取整体Person数据
public void onClick(View v) {
//获取EditText中输入文本
String name = et_example.getText().toString();
if (TextUtils.isEmpty(name)) {
return;
}
list.clear();
if (name.equals(person.getName())) {
list.add(person);
adapter.notifyDataSetChanged();
}
}
View与Model交互
以Adapter中的getView为例,Model与View之间能够直接进行交互,ListView中显示的控件都通过ViewHolder做了处理。关于ViewHolder就不做赘述了。
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = View.inflate(ExampleActivity.this, R.layout.layout_lv_example, null);
}
ViewHolder holder = ViewHolder.getInstance(convertView);
Person person = list.get(position);
holder.tv_lv_name.setText("name:" + person.getName());
holder.tv_lv_age.setText("age:" + String.valueOf(person.getAge()));
holder.tv_lv_gender.setText("gender:" + person.getGender());
holder.tv_lv_height.setText("height:" + String.valueOf(person.getHeight()));
holder.tv_lv_weight.setText("weight:" + String.valueOf(person.getWeight()));
return convertView;
}
至此,以上就是MVC的整体,事实上这一次总结对我帮助也很大,mvc设计模式的各个部分更加清晰。但是框架来说,最好还是经过使用才能最好的掌握。
总结
框架到底该怎样选择,这个实在还是该看实际情况。网络上搜索MVC经常看到”MVC已经落伍。。。”之类的帖子,但是事实上MVC在部分项目框架中依然好用,不必对其他新出现的框架迷信,适合项目的框架才是应该选用的框架。