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

Android设计模式之MVP

程序员文章站 2022-06-08 22:34:47
...

MVP模式

前言

  感觉自己的学习习惯一直不算很好,看书记笔记时也少了自己的见解而全是死的知识。所以打算开始写博客来表达自己的一些想法。

  现在也刚刚学习Android,以此来记录一下我的心得与笔记,因为是初学所以笔记也会显得很简单,每当我到了一定的阶段对这些知识有了新的见解我会来更新写过的文章,包括在初写的时候时间紧急而来不及附上的代码和图。最初的目的当然是为了鞭策自己,如果能帮助到你我也很高兴。

mvp模式是什么?

  更加为我们所知的应该是mvc模式,我们来先复习一下mvc模式。m是model层,v是view层,c是controller层,在MVC模式中允许view直接调用model层,而又因为Android的特殊性,Activity通常会担任view层和controller层,这样的话Activity就会显得特别臃肿。
  在mvp模式下,将许多Activity中的逻辑抽离在view层的UI接口上和presenter的业务接口上,并由具体的实现类来完成。
  之所以这样做是因为接口有不同的实现,方便做单元测试
  presenter层作为view层和model层的桥梁,同时禁止view对model的调用。

mvp的优点

  • 如上文所说,做单元测试是十分方便的。
  • 使Activity的代码更加简洁

mvp的缺点

  • 当一个项目过大时,会产生很多view接口和presenter接口

mvp代码实例

  • 先自己码一个很小很小的demo来说明一下什么是mvp模式,首先看一下项目结构

Android设计模式之MVP

主界面是一个登录的界面,判断登录是否成功

Android设计模式之MVP

两个接口文档分别如下所示:

    public interface IView {
        void login(boolean result);
    }


    public interface IPresenter {
        void Verify(String username,String password);
    }

Presenter的代码如下所示:

  • 检测用户名和密码是否正确往往需要查验数据库,可能是一个比较复杂的逻辑,所以应该放在Presenter层中。
  • 然后根据不同的判断结果给view层不同的提示。
  • presenter应该有一个view层的接口对象,并能通过构造函数将其初始化

    public class Presenter implements IPresenter {
    private IView mainView;

    public Presenter(IView view){
        mainView=view;
    }
    
    @Override
    public void Verify(String username, String password) {
        if(username.equals("Admin")&&password.equals("1234"))
            mainView.login(true);
        else
            mainView.login(false);
    }
    

    }

MainActivity的主要代码如下所示:

  • 在这个demo中,login就显得十分简洁,只需要依据presenter层给出的逻辑结果进行相应的UI操作。在代码量巨大的情况下能极大地简化Activity的操作
  • view层应该有一个Presenter的实例对象,如果需要进行测试的话。只需要更换对应的实例对象即可。单元测试十分方便。

    public class MainActivity extends AppCompatActivity implements IView{
        private Presenter presenter;
        private Button button;
        private EditText username;
        private EditText password;
        private String user;
        private String pwd;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            init();
        }
    
        public void init(){
            button = (Button) findViewById(R.id.login);
            username=(EditText) findViewById(R.id.username);
            password=(EditText) findViewById(R.id.password);
            presenter = new Presenter(this);
    
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    user=username.getText().toString();
                    pwd=password.getText().toString();
                    if(user==null||pwd==null||user.equals("")||pwd.equals(""))
                        Toast.makeText(MainActivity.this,"不能为空",Toast.LENGTH_LONG).show();
                    else
                        presenter.Verify(user,pwd);
                }
            });
        }
    
        @Override
        public void login(boolean result) {
            if(result)
                Toast.makeText(MainActivity.this,"登录成功",Toast.LENGTH_LONG).show();
            else
                Toast.makeText(MainActivity.this,"登录失败",Toast.LENGTH_LONG).show();
        }
    }
    

坑点

  • 因为我们有时会在presenter内开子线程进行比较耗时的操作,这时候我们就需要注意调用view接口的时候需要利用handler切换到主线程
  • 虽然Android不能在子线程更新UI基本上是每个工程师都知道的事情
  • 但是在真正开发的各种过程中还是有人会忽略,比如自己这个菜鸟就曾经因为在presenter进行网络请求而回调函数中直接调用的view接口函数而出问题。

后记

目前在做的有一定代码量的一个小项目也用到了mvp模式,有空的时候再整理一下。看看在代码量较大的情况下mvp模式的优点是否能比较清晰地凸显出来。