Mvp结构调整

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012359498/article/details/84582005

       先说说MVP和MVC的区别吧,MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller。


       在MVC里,View是可以直接访问Model的!从而,View里会包含Model信息,不可避免的还要包括一些业务逻辑。 在MVC模型里,更关注的Model的不变,而同时有多个对Model的不同显示,及View。所以,在MVC模型里,Model不依赖于View,但是View是依赖于Model的。不仅如此,因为有一些业务逻辑在View里实现了,导致要更改View也是比较困难的,至少那些业务逻辑是无法重用的。

       MVP针对MVC主要是取消掉了Model和View的直接通信,降低了耦合程度,主要的程序逻辑在Presenter里实现,这样在再经历UI大改版的时候业务逻辑也不会受到影响,我们改变的也只是View这块,既然是对MVP进行优化,先说说MVP的优点吧:

1.Model和View分离,View变化时不会影响Model

2.Model更容易管理,因为控制它的只有Presenter

3.主要逻辑放在Presenter中,易于管理和维护就不说了,像这块逻辑的完全可以单独作为一个Lib,作为一个java model 引入项目中,也方便进行业务测试

4.项目迁移方便,像一个视频直播平台,如果有多个app需要开发,那么这块业务逻辑完全是可以公用的,手机版和pad版或者是tv版,唯一不同的也就只有View不同,难道要copy3份代码,这样变更业务逻辑的时候将是相当痛苦的

       每种设计模式都有优点和缺点,接下来就是MVP的缺点了:

1.每个View有个Presenter,界面一多,就比较头疼了

2.多个Presenter管理不当可能造成业务处理耦合

3.每个Presenter都要为View里定义接口,有些定义了还无法重用,定义的接口太乱,有时会重复

       当然还有Mvvm模式Model-View-ViewModel ,google也提供了Data Binding 的方式,但是这种方式会把xml变得不再只是个单纯的View,Model一旦改动,还要改xml,xml的重用性也不高,因此不推荐此方式。

       接下来就是针对MVP的不足进行改造成适合自己的结构了,当然这三者的通信方式不会变动,现在对结构做出调整,一个View可以拥有多个Presenter,每个Presenter负责不同的业务,这里举例只有一个

这里没有说明Model,Model定义为获取数据的模型,实现方式有多样,首先定义View->Presenter和Presenter -> View的通信接口,为后面扩展方便


/**
 * 
 * Presenter -> View 进行通信
 */
public interface PresenterListener {
}



/**
 * 定义些给View操作的方法
 * View->Presenter   进行通信
 */
public interface I_UserPresenter {

    void login();

    void getInfo();

    interface OnGetUserInfoListener extends PresenterListener {
        void onGetUserInfo(Object info);
    }


    /**
     * 向Presenter触发业务操作
     *
     * @param roomId
     */
    void subUser(String roomId);

    void unSubUser(String roomId);

    /**
     * 向View通知状态
     */
    interface OnSubListener extends PresenterListener {
        /**
         * 返回订阅状态
         *
         * @param isSub
         */
        void onSubChange(boolean isSub);

    }

}

再看下Presenter的具体实现

public class UserPresenter extends CorePresenter implements I_UserPresenter {

    private OnGetUserInfoListener onGetUserInfoListener;
    private OnSubListener onSubListener;

    @Override
    public void login() {
        log("login");
    }

    @Override
    public void getInfo() {//可以根据不同的需求是读缓存还是网络,走不同的逻辑
        log("getinfo");
        if (onGetUserInfoListener != null) {
            onGetUserInfoListener.onGetUserInfo("test infos");
        }
    }

    @Override
    public void subUser(String roomId) {
        if (onSubListener != null) {
            //这里处理订阅的操作..省略
            log("subUser");

            onSubListener.onSubChange(true);
        }
    }


    @Override
    public void unSubUser(String roomId) {
        if (onSubListener != null) {
            //这里处理取消订阅的操作..省略

            log("unSubUser");
            onSubListener.onSubChange(false);
        }
    }

    @Override
    public void addListener(PresenterListener listener) {
        super.addListener(listener);
        if (listener instanceof OnGetUserInfoListener) {
            this.onGetUserInfoListener = (OnGetUserInfoListener) listener;
        } else if (listener instanceof OnSubListener) {
            this.onSubListener = (OnSubListener) listener;
        }

    }
}

再看下View里的结构

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (!mIsSub) {
                    userPresenter.subUser("");
                } else {
                    userPresenter.unSubUser("");
                }
            }
        });
        findViewById(R.id.tv).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                userPresenter.getInfo();
            }
        });
        userPresenter = new UserPresenter();

        userPresenter.addListener(onSubListener);//动态配置所需要的业务
        userPresenter.addListener(new I_UserPresenter.OnGetUserInfoListener() {
            @Override
            public void onGetUserInfo(Object info) {
                Toast.makeText(getBaseContext(), String.valueOf(info), Toast.LENGTH_LONG).show();
            }
        });
    }


    /**
     * View处理Presenter 相应的数据
     */
    private UserPresenter.OnSubListener onSubListener = new UserPresenter.OnSubListener() {
        @Override
        public void onSubChange(boolean isSub) {
            mIsSub = isSub;
            Snackbar.make(fab, "订阅状态" + isSub, Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    };

说下这样改的好处吧:

1.归类了Presenter,每个Presenter都有自己明确的职责,避免每个View都会有个Presenter 造成后续难以管理

2.每个Presenter可能有多个业务要处理,但不是每个都需要,可以通过添加Listener来去做需要的业务,这样不会造成一下子定义太多接口,有些接口在某些地方更不不需要

3.基本上Presenter每个业务处理都只匹配一个Listener,业务逻辑由Presenter来控制,方便一些好用的异步处理框架的快速切入(比如RxJava)和更换

4.代码量会减少

5.偶尔性降低

PS:适合自己的才是好的,框架不能定死了,个人见解而已,欢迎大家指出意见。

附上Demo

猜你喜欢

转载自blog.csdn.net/u012359498/article/details/84582005
MVP