Android架构探究之MVC设计模式
0. MVC进阶MVP阅读
Android架构探究之MVP设计模式: 点击阅读
1. 经典MVC模式介绍-Model-View-Controller
经典MVC模式中,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。其中,View的定义比较清晰,就是用户界面。[1]*
.
简单的解读:
1.View用户界面
指的是用户能看到的UI界面,更新UI界面只受到业务模型Model的控制,一旦Model有改动,则去通知View去更新UI界面。也可以说就是刷新数据的对应UI。
2.Model业务模型
指的是处理对数据的操作(下方我会列出代码,可以细看),数据操作包括了一些数据存储、增删改查、算法、网络请求等等。
3.Controller控制器
指的是响应用户的操作指令,并将指令发转发给Model进行相对应的数据处理。
4.流程举例说明:
当你点击了用户界面View层上的添加学生信息按钮,按钮发送一个指令到Model层去进行数据处理(将学生信息对象添加至list里,然后排序啊之类的)。Model层获取到了来自Controller层的指令,然后进行数据操作,操作完毕后就去通知View层更新UI界面。
5.流程结束对于用户意味着什么?:
这样的流程结束后用户(你)得到感觉就是,我按了这个按钮有反馈,我看到了UI的变化。
6.这样的流程对应于Android中的MVC模式是什么?:
继续看下文
2. Android的设计架构不同于经典MVC
经过经典MVC设计模式的介绍我们对整个流程有了初步的映像。但是对于Android来说可能不太一样。
- Andriod自身的设计结构是依照MVC的模式,但是又不完全一样
XML作为View层
,MainActivity既作为Controller层也充当了View层
V层与M层之间有联系,存在耦合
创建一个Android空项目的时候我们会发现有自动生成的几个文件。
XML
,MainActivity
。
XML
里的写的布局内容实际上就是APP对用户展示出来的UI效果。
同时我们可以在MainActivity
中可以用findViewById
方法从填充的布局xml中获取对应的组件,并监听其各种事件。例如监听Button的click事件,我们就可以在activity层里响应用户的操作指令了。.
当我们响应用户的操作后,会对数据进行处理,处理完毕后还是在MainActivity里通过绑定好的组件对象去更新相应的UI。
所以说
XML作为View层向用户展示了UI界面
,MainActivity作为Controller层响应了用户的操作指令
,与此同时MainActivity也分担了Viewl层
的功能去更新UI界面。
- MainActiviy可以担任多个角色,这就导致了有的开发者会在MainActivity里写Model层的数据处理,这样可以省去传递信息通知的步骤,直接再MainActivity操作去对View层进行UI更新,方便是肯定的。但是会使得一个MainActivity文件的代码量暴增,非常糟糕!
3. 在Android中如何实现标准的MVC设计架构?
- 需求假设:
*点击按钮创建一个学生信息,添加至列表里,并用文本并展示出被添加的学生信息。点击删除按钮,
*删除一个学生信息,并用文本并展示出被删除的学生信息。 - xml布局:两个按钮,一个文本
尽量将
Activity
的多角色分离出来。
创建一个StudentController.java作为Activity的Controller层
。
创建一个StudentModel.java作为Activity的M层
。
那么Activity做什么?因为我们是在Activity中与xml进行联系,所以尽可能只提供方法对View层进行更新。
.
public class StudentBean {
//学生名字
private String name = "";
//学生ID
private int id = -1;
//学生性别
private String gender = "";
//枚举-性别
public enum Gender {
男, 女
}
//创建学生对象的时候,必须传入3个参数,名字,ID,性别
public StudentBean(String name, int id, Gender gender) {
this.name = name;
this.id = id;
this.gender = gender == Gender.男?"男":"女";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
/**
* 接口,M层处理完毕后,会对所有注册过的接口发送消息
*/
public interface OnUpdateViewListener {
//添加用户后回调
void OnModelAddStudentCompleted(StudentBean studentBean);
//删除用户后回调
void OnModelRemoveStudentCompleted(String studentName);
}
public class MainActivity extends AppCompatActivity {
private Button vBtnDelete,vBtnAdd;
private TextView vTvTotalPeopleAmount, vTvStudentInfo;
//Controller层
private StudentController studentController = StudentController.getInstance();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initial();
addListener();
studentController.setMainActivity(this);
}
private void initial(){
vBtnDelete = findViewById(R.id.vBtnDelete);
vBtnAdd = findViewById(R.id.vBtnAdd);
vTvTotalPeopleAmount = findViewById(R.id.vTvTotalPeopleAmount);
vTvStudentInfo = findViewById(R.id.vTvStudentInfo);
}
private void addListener(){
//监听 添加按钮 的点击事件
vBtnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//随机一个id,性别,姓名
int max=100,min=1;
int id = (int) (Math.random()*(max-min)+min);
//new一个学生对象,并将响应用户的点击事件与所要处理的信息一并交给Controller层进行处理
studentController.addStudent(new StudentBean("张三-"+id ,id,id<=50?StudentBean.Gender.男:StudentBean.Gender.女));
}
});
//监听 删除按钮 的点击事件
vBtnDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//将响应用户的删除点击事件与所要处理的信息一并交给Controller层进行处理
studentController.removeStudent(0);
}
});
}
//提供更新UI的方法
public void updateViewUi_studentAmount(int studentAmount){
if(null != vTvTotalPeopleAmount){
vTvTotalPeopleAmount.setText(""+studentAmount);
}
}
//提供更新UI的方法
public void updateViewUi_addedStudent(StudentBean studentBean){
if(null != vTvStudentInfo){
vTvStudentInfo.setText(
"被添加的学生信息:"+
"\n名字:"+studentBean.getName()+
"\n学号: "+studentBean.getId()+
"\n性别: "+studentBean.getGender());
}
}
//提供更新UI的方法
public void updateViewUi_removeStudent(String studentName){
if(null != vTvStudentInfo){
vTvStudentInfo.setText(studentName);
}
}
}
public class StudentController implements OnUpdateViewListener{
private static volatile StudentController mInstance = null;
public StudentController(){}
//创建M层实例
private StudentModel studentModel = new StudentModel();
//MainActivity
private MainActivity mainActivity;
//DCL
public static StudentController getInstance(){
if(mInstance == null){
synchronized (StudentController.class){
if(mInstance == null){
mInstance = new StudentController();
}
}
}
return mInstance;
}
/**
* 向Model层发送添加学生数据的指令
* @param studentBean
*/
public void addStudent(StudentBean studentBean){
//将储存学生对象的数据操作,交给StudentModel去处理
studentModel.addStudent(studentBean);
}
/**
* 向Model层发送删除学生数据的指令
*/
public void removeStudent(int index){
//将储存学生对象的数据操作,交给StudentModel去处理
studentModel.removeStudent(index);
}
/**
* 将MainActivity传入至Controller。实际上Activity本来就充当Controller的角色,
* 但是Activity同时又操作如何对V层更新的逻辑,所有的逻辑都写在Activity里代码量会非常大,不利于维护。
* 所以我们把部分方法抽离出来,写成独立的Controller
* @param mainActivity
*/
public void setMainActivity(MainActivity mainActivity){
this.mainActivity = mainActivity;
//向M层注册接口监听数据处理完成的事件
studentModel.addOnUpdateViewListener(this);
}
//实现接口,调用activity提供更新V层的方法
@Override
public void OnModelAddStudentCompleted(List<StudentBean> mStudentList, StudentBean studentBean) {
mainActivity.updateViewUi_studentAmount(mStudentList.size());
mainActivity.updateViewUi_addedStudent(studentBean);
}
//实现接口,调用activity提供更新V层的方法
@Override
public void OnModelRemoveStudentCompleted(List<StudentBean> mStudentList, String studentName) {
mainActivity.updateViewUi_studentAmount(mStudentList.size());
mainActivity.updateViewUi_removeStudent(studentName);
}
}
public class StudentModel {
//list储存所有实现的接口
private List<OnUpdateViewListener> mListenerList = new ArrayList<>();
//学生对象list
private List<StudentBean> mStudentList = new ArrayList<>();
/**
* 添加接口
*/
public void addOnUpdateViewListener(OnUpdateViewListener onUpdateViewListener){
if(!mListenerList.contains(onUpdateViewListener)){
mListenerList.add(onUpdateViewListener);
}
}
/**
* 添加学生方法
* 从Controller获取到学生对象数据后,对该数据进行操作,添加至学生list中。
* 数据操作完毕后,通知View层进行更新UI事件
* @param studentBean
*/
public void addStudent(StudentBean studentBean){
if(null != mStudentList && null != studentBean){
if(!mStudentList.contains( studentBean )) {
mStudentList.add(studentBean);
//把数据处理结束的消息,发送到所有实现的接口
for(OnUpdateViewListener listener: mListenerList){
listener.OnModelAddStudentCompleted(mStudentList,studentBean);
}
}
}
}
//删除学生对象
public void removeStudent(int index){
if(null != mStudentList && index>=0){
String studentName = "删除:学生: "+mStudentList.get(index).getName() +" 性别: "+mStudentList.get(index).getGender() +" 学号:"+mStudentList.get(index).getId();
mStudentList.remove(index);
//把数据处理结束的消息,发送到所有实现的接口
for(OnUpdateViewListener listener: mListenerList){
listener.OnModelRemoveStudentCompleted(mStudentList,studentName);
}
}
}
}
4. 完成代码请看github
- MVC设计模式 Github项目地址: 点击跳转
5. Android技术生活交流
qq群
[1]* 百度文献