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层进行更新。


  • 0. 项目结构 - gif 演示

.
在这里插入图片描述

  • 1. 首先我们创建个学生信息Bean类,StudentBean。和一个接口 OnUpdateViewList作为M层处理完毕后给C层的回调。
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);
}


  • 2. Activity里做两件事,1,绑定xml中的控件并监听点击事件。2,向C层提供更新V层UI的可调用方法。
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);
        }
    }

}


  • 3. C层,StudentController里做两件事。1,响应Activity传来的点击事件转发给M层、2.拿到M层处理完毕后的回调,去调用Activity里提供出来的更新V层UI的方法。

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);
    }
}

  • 4. M层,StudentModel里做两件事,1,对从C层拿到的数据做处理、2,处理完毕后通过接口把消息发出去。

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


5. Android技术生活交流

qq群



[1]* 百度文献

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值