欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

android基础—Android常见项目架构示例mvc、mvp、mvvm

程序员文章站 2022-03-31 07:59:24
对于移动端来说他的架构都非常简单,系统性的架构设计一般是用于大型项目,比如web服务,做网站的,他们一般都需要系统性的架构设计,因为一做就是很大的东西,好几十人一起做。而对移动端,一般来说,简单架构就足够了,除非软件非常大,比如淘宝,淘宝超级大,还有其他国内一些大团队做的应用,这些东西太大了,我需要系统性地去设计一些架构,才能够hole住他,才能让他做得很大的时候不会散不会乱,不会跑不动,架构这东西,所有软件都会有,不是你需不需要,他是一定会有的。哪怕一开始没有,你做着做着就有了。不够你做着做着再去想他,你...

对于移动端来说他的架构都非常简单,系统性的架构设计一般是用于大型项目,比如web服务,做网站的,他们一般都需要系统性的架构设计,因为一做就是很大的东西,好几十人一起做。而对移动端,一般来说,简单架构就足够了,除非软件非常大,比如淘宝,淘宝超级大,还有其他国内一些大团队做的应用,这些东西太大了,我需要系统性地去设计一些架构,才能够hole住他,才能让他做得很大的时候不会散不会乱,不会跑不动,架构这东西,所有软件都会有,不是你需不需要,他是一定会有的。哪怕一开始没有,你做着做着就有了。不够你做着做着再去想他,你改的时候会比较累。就是移动端的架构通常来说都是非常简单的。虽然移动端的架构很简单,但是对于mvc、mvp、mvvm,对他们的误解是很大的。

1.架构有什么用?

对于web项目来说,他们的架构虽然大,但是架构设计并没有很难,是因为有很多成熟的框架可以用,不管你是用php还是node、java都是有很多成熟的框架的,不过有成熟框架就是因为这个东西很复杂,所以有些成熟框架大家做出来都用,有很多人尝试,有很多人认可,最终剩下几个活着的很好。这个框架本身就提供了项目的架构了,这些框架提供的架构,框架就是framework,就是你把她这一套东西拿过来,按他的公式去套进去用,这是框架。而架构是你项目的结构,比如你什么东西放在哪个目录,然后你代码哪个东西写在哪个方法里面,什么东西写在哪个类里面,这是你的架构。框架是他给你套的一个束缚,一个约束,然后你写起来也比较轻松。也就是说你通过使用框架的方式,就把项目的架构搭建好了,你也用这个框架,我也用这个框架,那么我们的架构是一样的。这个是对于很多大项目来说,尤其是传统的web项目来说,他们一般是这样的,而对于android开发来说,不一样,android SDK 他提供的方案就可以写出完整的软件了,我们不需要去遵守各种东西,因为对于一些web项目来说,你不用框架行不行?能行,但是对于他们来说,他们用什么写?他们用语言写,比如我用php来写,我用java来写,我用js来写,或者我用node来写。而对于android开发,我们是用android SDK 来写,我们不会说我们用java写一个android项目。其实他们也是这样的,他们如果只用他们语言本身,去搭一个网站,行不行?能行,但是太麻烦了。android强制我们用他的SDK,才能做软件开发,但是他强制的同时,也对我们制定出各种各样的规则,比如我们只能在activity里面去写界面,然后图标必须在什么地方去设置,通过这些规则去限制,我 们已经能用比较稳定的代码来写软件了,你写也稳定,我写也稳定,学个三天就能上手,写个软件运行起来不会奔溃,只要你写的软件足够简单,都不会奔溃,因为我们只有这一种方法写。这个是android SDK 对我们提供的限制,同时也让我们写起来会比较稳定。

然后,由于移动端的软件功能是相对简单的,所以写简单软件你也不需要再加额外架构,但是如果是商业项目,你没有架构,那会有什么坏处呢?

1.不同的人风格不同,一个人写的代码结构换个人可能会看不懂。咱都*写,我写的代码你可能看不懂。每个团队也有自己的风格和规范,来了一个新人的时候,他看懂团队代码可能会有门槛

2.项目越做越大的时候可能会面临改不动的问题,软件结构不好调整。项目做得越大,这种风险就会越大。

2.mvc、mvp、mvvm的主流理解

android基础—Android常见项目架构示例mvc、mvp、mvvm

3.mvc

class View {
    //相当于xml
    //用来显示以及把用户事件传给controller
    Controller controller;

    void showData(int data) {
        //...
    }

    void clicked() {
        controller.viewClicked(this);
    }
}

class Controller {
    //相当于activity
    //用来调度,去操作model,让他去执行业务逻辑,他告诉model你要做什么?model再具体去实现。
    Model model;

    void viewClicked(View view) {
        switch (view.getId()) {
            case R.id.bt:
                model.dataAdd(1);
                break;

        }
    }
}

class Model {
    //相当于相关数据操作类
    //将实现结果给view,让view去更新
    int data;
    View view;
    public void dataAdd(int delta) {
        data += delta;
        view.showData(data);
    }
}

这种开发结构有一种缺陷,controller和view结合太紧密了,activity会一行一行操作view,我是把结果交给view去做,但是我对view的干涉也太多了,我并不是告诉他数据是这个你去显示吧。而是把每一行告诉他你要怎么做,你的这个控件要这么显示。这样写,你的的逻辑比较复杂的时候,controller和view就缠在一起了。你的view的显示内容的改变总要c去做具体操作。而不是让view去做具体操作。

4.mvp

mvp之所以比mvc更有优势,并不是mvp的思想本身,而是mvp代码的是实现,从代码的结构上把presenter和view拆开了,mvc是透明两个有耦合,而mvp从代码上,物理上,把v和p给拆开了,这是他们的主要区别。本质上他们的三层结构是差不多的。
有一种说法,mvp因为切断了v和m之间的链接,让代码更加松散了,因此更有优势。但是,我们平时写代码也没有把m和v连接(mvc变种)。所以这种说法是站不住脚的。
还有一种说法,mvp通过把p单独抽出来,强行隔离了v和p,由于mvp具有这个特性,所以跟mvc不一样了。因为mvc最大劣势就是c和v都在activity里面。他们的关系他紧密了。这种说法对不对等会讨论。
主流的mvp就是把mvc里的c从activity里面抽出来,抽出来的那一部分叫p,而mvp里面,activity里面只留下了v那一部分。
m:

public class DataCenter {
    public static String[] getData() {
        return new String[]{"1","2"};
    }
    public static void setData(){

    }
}

v:

public class MvpActivity extends AppCompatActivity implements Presenter.IView {
    private EditText et1;
    private EditText et2;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mvp);

        et1 = findViewById(R.id.et1);
        et2 = findViewById(R.id.et2);

        new Presenter(this).load();
    }

    @Override
    public void showData(String data1, String data2) {
        et1.setText(data1);
        et2.setText(data2);
    }
}

p:

public class Presenter {
    IView iView;
    Presenter(IView iView){
        this.iView = iView;
    }
    void load(){
        String[] data = DataCenter.getData();
        iView.showData(data[0],data[1]);
    }

    interface IView{
        void showData(String data1,String data2);
    }
}

也可以把v从activity里面拆出来,保留c,就自定义view继承LinerLayout,然后把view的功能转移到自定义view里面。然后p可以写在activity里面,控制的接口让自定义去实现。(这种应该没什么人用吧,用来演示mvc也可以把m和v拆开,用c来控制)

5.mvvm

程序里面有三种数据,数据库数据(包括网络数据),内存数据(也就是java里的变量),表现数据(界面展示的数据)。双向绑定就是内存数据和表现数据实时地互相更新。
让mvp不用setdata绑定数据,让他们load的时候就双向绑定,就是mvvm。mvvm大致就是一个双向绑定的mvp。

public class MvvmActivity extends AppCompatActivity {
    private EditText et1;
    private EditText et2;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mvp);

        et1 = findViewById(R.id.et1);
        et2 = findViewById(R.id.et2);

        new ViewModel(new ViewBinder(),et1,et2).load();

    }

}

public class ViewBinder {
    void bind(EditText editText, final ViewModel.TextAttr text) {
        //怎么绑定,监听器,但是text怎么监听呢?包起来,在ViewModel里面
        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                if (!s.equals(text.getText())) {
                    text.setText(s.toString());

                }
            }
        });
        text.setOnChangeListener(new ViewModel.TextAttr.OnChangeListener() {
            @Override
            public void onChange(String newTexr) {
                if (!newTexr.equals(editText.getText().toString())) {
                    editText.setText(newTexr);
                }
                System.out.println("被动改变:"+newTexr);
            }
        });

    }
}


public class ViewModel {
    TextAttr data1 = new TextAttr();
    TextAttr data2 = new TextAttr();

    ViewModel(ViewBinder binder, EditText et1,EditText et2){
        binder.bind(et1,data1);
        binder.bind(et2,data2);
    }

    void load() {
        String[] data = DataCenter.getData();
        data1.setText(data[0]);
        data2.setText(data[1]);
    }

    static class TextAttr {
        private String text;
        private OnChangeListener listener;

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
            if (listener != null) {
                listener.onChange(text);
            }
        }

        void setOnChangeListener(OnChangeListener listener){
            this.listener = listener;
        }
        interface OnChangeListener {
            void onChange(String newTexr);
        }
    }
}


public class DataCenter {
    public static String[] getData() {
        return new String[]{"1","2"};
    }
    public static void setData(){

    }
}

本文地址:https://blog.csdn.net/qq_36333289/article/details/110239460