MMP???不是,是MVP

作者: 上官若枫 | 来源:发表于2017-12-04 14:22 被阅读720次

    本篇文章代码引用GitHub上zhihu项目,https://github.com/yiyibb/Zhihu。在这里跟初学者强烈推荐一下,这个项目功能虽然简单,只是一个简单阅读功能,但是我很佩服开发者的代码封装能力,做的真得很完美。采用的是MVP+retrofit+rxjava架构。今天主要看他的架构分析。

    MVP

    我们在初学android的时候,用的架构都是MVC,何为MVC呢。model,view,control。简单来讲model就是数据层,view就是activity,control就是逻辑处理。
    开始学的MVC很容易理解,所有层都能在activity上看到,逻辑也很容易看清。activity能够和model,view两者互相接触。但同时也带来相当的困扰,耦合性太大。你想啊,只要activity改动很容易牵连到方面,而且activity任务量也比较大。
    由此从MVC衍生出MVP,MVP很大程度上解决了耦合性的问题,view层不再能直接接触model,我感觉这个应该是最大的亮点。当然还有其他优势,比如更方便进行单元测试等等。具体的网上查一查就明白了。

    retrofit+rxjava

    一个是网络请求,一个是异步处理,由于本文主要讲架构分析,这些用法不会赘述。推荐读者看一看开发者抛物线的文章。上面说过了我是引用别人的代码,其实刚开始我用的就是MVC开发模式,没有全部按照他的写。很蹩脚,重构代码真的很费劲。当初也只是想切身体验一下两个架构的区别,结果越整越乱,重点是我并不是很熟悉MVP的结构模型

    架构搭建

    首先分析一下功能,从api拿到json数据,然后用retrofit开始解析,拿到数据后用rxjava更新UI集合。来看看整体架构,代码是从项目里摘出来的,功能也已经实现,链接如下https://github.com/ZhangPeng0220/MVP_Retrofit_Rxjava

    image.png
    整体有一个mvp架构放在了 mvp_base文件夹里面,drawerMvp是整体项目的一个侧滑栏模块,DrawerMainContract类里包含了drawer模块需要的model,view,presenter。api是model数据连接,common里也是一些基类。接下来可以分层分析。

    Drawer MVP模块

    这里主要介绍DrawerMainContract接口类

    public interface DrawerMainContract {
    
        interface Model extends BaseModel {
            Observable<ThemesEntity> getOtherThemeList();
        }
    
        interface View extends BaseView {
            void loadOtherThemeList(ThemesEntity themesEntity);
        }
    
        abstract class Presenter extends BasePresenter<Model,View> {
            abstract void getOtherThemes();
        }
    }
    

    这里所有最终的实体类,都会实现DrawerMainContract中的接口。比如mainactivity会实现view接口

    View

    这里的view层显而易见就是mainActivity

    public class MainActivity extends BaseFrameActivity<DrawerMainPresenter,DrawerMainModel> implements BaseView, DrawerMainContract.View{
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mPresenter.getOtherThemes();
        }
    
        @Override
        public void loadOtherThemeList(ThemesEntity themesEntity) {
            //处理返回结果
            themesEntity.getLimit();
        }
    }
    

    BaseFrameActivity继承自BaseActivity,除了拥有activity的一般生命周期方法以外,它还主要实现了model和presenter的实例化。

    public abstract class BaseFrameActivity<P extends BasePresenter, M extends BaseModel> extends BaseActivity implements BaseView{
        public P mPresenter;
    
        public M mModel;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mPresenter = TUtil.getT(this, 0);
            mModel = TUtil.getT(this, 1);
            if (this instanceof BaseView) {
                mPresenter.attachVM(this, mModel);
            }
        }
        @Override
        protected void onDestroy() {
           /// if (mPresenter != null) mPresenter.detachVM();
            super.onDestroy();
        }
    
    
    }
    

    实例化是通过工具类 TUtil实现的,具体代码请读者移步上文的GitHub地址。这里需要注意的有三个点:
    第一个是泛型限制,传入的presenter和model都有父类限制。
    第二个需要注意的是,在view层只会接触到presenter,不会接触model,为啥这边还要实例化model。这里的model实例其实为presenter准备的。mPresenter.attachVM(this, mModel)这句话是关键。
    第三个是baseview这里是空的,这里可以放一些基本的方法,比如initview,initdata

    Presenter

    public abstract class BasePresenter<M, V>  {
        public M mModel;
        public V mView;
      
        public void attachVM(V v, M m) {
            this.mModel = m;
            this.mView = v;
    
        }
    
        public void detachVM() {
            //mRxManager.clear();
            mView = null;
            mModel = null;
        }
    }
    

    BasePresenter主要用于刚刚view和model的实例化。由于这个类有实体方法并未使用接口。接下来就是DrawerMainContract.Presenter继承了这个抽象方法,具体实现类是DrawerMainPresenter

    public class DrawerMainPresenter extends DrawerMainContract.Presenter{
    
        @Override
         public void getOtherThemes() {
            mModel.getOtherThemeList()
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Subscriber<ThemesEntity>() {
                        @Override
                        public void onCompleted() {
    
                        }
    
                        @Override
                        public void onError(Throwable e) {
                           // mView.onRequestError("数据加载失败ヽ(≧Д≦)ノ");
                        }
    
                        @Override
                        public void onNext(ThemesEntity themesEntity) {
                            mView.loadOtherThemeList(themesEntity);
                        }
                    });
        }
    }
    

    mModel.getOtherThemeList()这个方法是属于model层的,会返回一个Observable对象,这就属于RxJava的内容了,当得到了具体数据,会在onNext方法里面调用view更新数据的方法,此时mView已经在BaseFrameActivity中的mPresenter.attachVM方法实例化了。

    Model

    这一层主要是用于连接数据,调用数据。

    public class DrawerMainModel implements DrawerMainContract.Model{
        @Override
        public Observable<ThemesEntity> getOtherThemeList() {
            return Networks.getInstance().getThemeApi().getThemes();
        }
    }
    

    DrawerMainModel实现的接口没啥可讲的,方法可以看一看

    public MyService getThemeApi() {
            return mThemeApi == null ? configRetrofit(MyService.class) : mThemeApi;
        }
    
        private <T> T configRetrofit(Class<T> service) {
            retrofit = new Retrofit.Builder()
                    .baseUrl("http://news-at.zhihu.com")
                    .client(configClient())
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .build();
            return retrofit.create(service);
        }
    
        private OkHttpClient configClient() {
            OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder()
                    .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
            return okHttpClient.build();
        }
    

    这是network里面的实现方法,getThemeApi()方法主要是拿到myservice的实例,继而调用myservice中的getThemes(),拿到json数据。

    总结

    整体流程就是上面得了,其实不算难,但是作者的封装风格我比较喜欢。流程图如下。可以看出 和MVC相比较是清晰了很多。


    image.png

    感兴趣的同学可以关注一下我的微信公众号,或者微信搜索 开发 Android的小学生


    公众号.jpg

    相关文章

      网友评论

      本文标题:MMP???不是,是MVP

      本文链接:https://www.haomeiwen.com/subject/psdwbxtx.html