美文网首页AndroidMVP项目Yzs的Android进阶之路
MVP架构开发,一篇让你从看懂到会使用

MVP架构开发,一篇让你从看懂到会使用

作者: 小小一瓶水 | 来源:发表于2017-06-26 21:14 被阅读288次

    本博客现已与码个蛋形成合作,独发码个蛋

    Android百科全书二维码.jpg

    本人最新公众号<Android百科全书>,汇集了各个公众号的优秀文章,进行分类整理,让大家能够更方便的查阅,希望大家多多支持,来个关注奥。

    Yzs专属头像

    现在网上关于mvp架构的文章有很多,但是对于一些不是特别理解这个架构的开发者,不是很友好,所以,我要写一篇博客,通过我的努力,让大家能够更好的理解他,并使用他。下面是我这片文章要讲解的内容

    • mvp到底是个什么东西
    • 对mvp架构设计思路分析
    • mvp架构的基本设计、使用
    • 对于mvp架构的个人理解

    下面让我们从第一部开始,一步步走进mvp:

    1. mvp到底是个什么东西:

    我们所说的mvp架构,是google开源的一个设计模式,目的是为了将代码更加优雅清晰的呈现出来,废话也不多说,直接分析
    
    M:M层,也就是我们在程序中经常出现的model层,他的功能就是处理数据,其他任务不由他来接手。
    V:V层,我们的view层,也就是显示数据的地方,我们在得到数据之后,把数据传递给view层,通过他来显示数据。同时,
    view层的点击事件等处理会在这里出现,但真正的数据处理不是在这里,而是在model层中处理。
    P:P层,也就是Presenter层,他是我们mvp架构中的中间人,通过p层的连接,让我们可以是M层和V层进行通信。M层在获
    取到数据之后,把它交给P,P层在交给View层,同样,View层的点击事件等处理通过P层去通知M层,让他去进行数据处理。
    
    
    通过这样的mvp交流,使程序有了一个模块的拆分,使逻辑更加的清晰,明白。
    

    2. 对mvp架构设计思路分析

    一些开发者不使用mvp架构不是因为觉得这个架构不好,而是没弄明白这个架构到底是怎么个逻辑,所以在这里,把我自己对于他
    的理解分享给大家,作为大家的参考,共同学习进步。
    mvp架构的中心思想我认为就是面向接口编程,调用层使用接口对象,去调用接口方法,实现层去实现接口方法,并在调用层实例化。
    
    面向接口编程
    比如我们要做一个加载图片的抽象方法也就是下面的这片代码
    
    public interface ImageLoaderInterface<T extends View> extends Serializable {
    
        void displayImage(Context context, String path, T imageView);
    
        void displayImage(Context context, @DrawableRes Integer resId, T imageView);
    
        T createImageView(Context context);
    }
    

    我们使用的时候就是直接去使用它的方法,比如我们要在adapter中使用他, 那么我们不需要在adapter中去实例化他,而是直接使用这个接口对象,在使用的地方调用接口的方法

      public ImageLoaderInterface imageLoaderInterface;
    
        public void showPic(ViewHolder holder) {
          
                imageLoaderInterface.displayImage(context, addPicRes, holder.iv_pic);
    
            } 
    
    

    然后我们在其他类中去写它的实现类,在adapter的初始化中把这个实现类去传递给他

    
    public abstract class ImageLoader implements ImageLoaderInterface<ImageView> {
    
        @Override
        public ImageView createImageView(Context context) {
            return new ImageView(context);
        }
    
    }
    
    public class Loader extends ImageLoader {
    
        @Override
        public void displayImage(Context context, String path, ImageView imageView) {
            Glide.with(context).load(path).into(imageView);
    
        }
    
        @Override
        public void displayImage(Context context, @DrawableRes Integer resId, ImageView imageView) {
            imageView.setImageResource(resId);
        }
    
    }
    
    
    adapter中写set方法,让外部调用
    
    adapter.setImageLoaderInterface(new Loader());
    
    

    这个就是面向接口编程的一种实现方式,明白了这个,我们就可以继续往下说了。

    mvp架构中,我们要把m层的接口方法抽象出来,p层的接口方法抽象出来,v层的接口方法抽象出来,同时分别写3个接口的实现类,(v层一般是activity或者fragment继承view层的接口),v层持有p的接口对象,p层持有v层和m层的接口对象,m层为p层的提供数据,这时也就形成了mvp架构,三者之间通过p层相互连接

    3. mvp架构的基本设计、使用

    写一个简单的例子,我们要做的就是通过在activity中一个按钮的点击事件,来获取数据,下面上代码
    

    首先我们要定义出mvp的所有接口

    public interface TestContract {
    
        interface View {
            //显示数据
            void showData(String str);
        
        }
    
        interface Presenter  {
             //通知model要获取数据并把model返回的数据交给view层
            void getData();
    
        }
    
        interface Model {
             //获取数据
           String doData();
    
        }
    }
    
    

    实现p接口

    public class TestPresenter implements TestContract.Presenter {
    
        private TestContract.Model model;
        private TestContract.View view;
    
        public TestPresenter (TestContract.Model model, TestContract.View view) {
            this.model = model;
            this.view = view;
        }
    
    
        @Override
        public void getData() {
          view.showData(model.doData());    
        }
    
     
    }
    

    实现m接口

    public class TestModel implements TestContract.Model {
        private TestModel model;
    
        public static TestModel getInstance() {
            if (model== null) {
                model= new TestModel ();
            }
            return model;
        }
        
        @Override
        public  String doData() {
            
            return "mvp架构";
        }
    
    
    }
    

    让activity继承v接口,并且初始化p,让p持有m和v

    public class TestActivity extends Activity implements TestContract.View,View.OnClickListener {
    private TestContract.Presenter  presenter;
    
     presenter = new TestPresenter (TestModel.getInstance(), this);
    
    ...
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.tv_test: // 回到顶部按钮
                    presenter.getData();
                    break;
                   }
        }
    
        @Override
        protected void showData(String str) {
            textVeiw.setText(str)
        }
    }
    
    
    

    就这样,我们一个最简单的mvp例子就写出来了,多的废话不说这个例子是不是很简单直观,我们要的就是这样的效果,通过最直接,
    最简单的方法让你理解这个架构的使用,然后我们在一起深入的研究他,紧接着,我们要在这简单的使用上挖掘较优方案了

    4. 对于mvp架构的个人理解

    google在github发布的mvpdemo相信很多人都看过,但是我感觉许多人认为这不是最优方案,为什么呢?
    因为我们在日常开发中,很多网络请求是重复的,比如加入购物车,这个接口会在商品详情中出现,也可能会在商品列表中出现,
    在购物车的数量更改上也可能用到它,如果不复用他,我们就在每个界面的model层中去复制粘贴他,但是这样又远离的mvp的中
    心思想,mvp就是想让你在最大程度上复用,减少无用代码,那么这样的接口我们应该怎样处理呢。
    对于这个问题我有几个思路
    ===============================================================
        1.  我们可以让一个p层去持有多个model,通过这样的方式来复用model;
        2.  我们可以让一个view持有多个p,每个p去调用不同的model分别处理不同的事务;
        3.  我们可以将model模块进行拆分,将大量复用的model单独拆分出来,让这个model可以去被其他model调用,这样也实现了最大程度上的复用;
    

    4.1 一个p层去持有多个model方案,只有Presenter层需要特殊处理,其他同上方基础例子

    
    public class MoreModelPresenter implements MoreModelContract.Presenter {
    
        private MoreModelContract.OneModel oneModel;
        private MoreModelContract.TwoModel twoModel;
        private MoreModelContract.ThreeModel threeModel;
        private MoreModelContract.View view;
    
        public MoreModelPresenter(MoreModelContract.OneModel oneModel, MoreModelContract.TwoModel twoModel, MoreModelContract.ThreeModel threeModel, MoreModelContract.View view) {
            this.oneModel = oneModel;
            this.twoModel = twoModel;
            this.threeModel = threeModel;
            this.view = view;
        }
    
    
        @Override
        public void getData1() {
            view.showData1(oneModel.doDataOne());
        }
    
        @Override
        public void getData2() {
            view.showData1(twoModel.doDataTwo());
        }
    
        @Override
        public void getData3() {
            view.showData1(threeModel.doDataThree());
        }
    }
    

    4.2 单V多p多m架构

    
    public class MainActivity extends AppCompatActivity implements MorePresenterContract.View {
    
        private MorePresenterOne morPresenterOne;
        private MorePresenterTwo morePresenterTwo;
    
        @Override
    
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            morPresenterOne = new MorePresenterOne(MorePresenterModelOne.getInstance(), this);
            morePresenterTwo = new MorePresenterTwo(MorePresenterModelTwo.getInstance(), this);
    
            findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    morPresenterOne.getData1();
                }
            });
    
            findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    morePresenterTwo.getData2();
                }
            });
    
        }
    
        @Override
        public void showData1(String str) {
            Toast.makeText(this,str,Toast.LENGTH_SHORT).show();
        }
    
        @Override
        public void showData2(String str) {
            Toast.makeText(this,str,Toast.LENGTH_SHORT).show();
        }
    }
    
    
    //mvp接口类
    public interface MorePresenterContract {
        interface View {
            //显示数据
            void showData1(String str);
            void showData2(String str);
    
        }
    
        interface PresenterOne {
            //通知model要获取数据并把model返回的数据交给view层
            void getData1();
    
        }
    
        interface PresenterTwo {
            //通知model要获取数据并把model返回的数据交给view层
            void getData2();
    
        }
    
        interface ModelOne {
            //获取数据
            String doData1();
    
        }
    
        interface ModelTwo {
            //获取数据
            String doData2();
    
        }
    }
    
    
    
    //第一个p
    public class MorePresenterOne implements MorePresenterContract.PresenterOne {
    
        private MorePresenterContract.ModelOne modelOne;
        private MorePresenterContract.View view;
    
        public MorePresenterOne(MorePresenterContract.ModelOne modelOne, MorePresenterContract.View view) {
            this.modelOne = modelOne;
            this.view = view;
        }
    
        @Override
        public void getData1() {
            view.showData1(modelOne.doData1());
        }
    }
    
    
    
    //第二个p
    public class MorePresenterTwo implements MorePresenterContract.PresenterTwo {
        private MorePresenterContract.ModelTwo modelTwo;
        private MorePresenterContract.View view;
    
        public MorePresenterTwo(MorePresenterContract.ModelTwo modelTwo, MorePresenterContract.View view) {
            this.modelTwo = modelTwo;
            this.view = view;
        }
    
        @Override
        public void getData2() {
            view.showData2(modelTwo.doData2());
        }
    }
    
    //model就是普通写法
    public class MorePresenterModelOne implements MorePresenterContract.ModelOne {
        private static MorePresenterModelOne morePresenterModelOne;
    
        public static MorePresenterModelOne getInstance() {
            if (morePresenterModelOne == null) {
                morePresenterModelOne = new MorePresenterModelOne();
            }
            return morePresenterModelOne;
        }
    
        @Override
        public String doData1() {
            return "MorePresenterModelOne";
        }
    }
    
    
    

    4.3 model模块拆分,将大量复用的model单独拆分出来,让这个model可以去被其他model调用

    
    
    public interface ModelIncludeModeContract {
    
        interface View {
            //显示数据
            void showData(String str);
    
        }
    
        interface Presenter {
            //通知model要获取数据并把model返回的数据交给view层
            void getData();
    
        }
    
        interface Model {
            //获取数据
            String doOtherDataOne();
            //
            String doOtherDataTwo();
    
        }
    
    }
    
    
    public class OneModelIncludeOther implements ModelIncludeModeContract.Model {
    
        private IOtherMode otherMode;
        private IOtherModeTwo otherModeTwo;
        /主model使用时去初始化其他子model,让主model可以调用子model的方法
        public OneModelIncludeOther(IOtherMode otherMode, IOtherModeTwo otherModeTwo) {
            this.otherMode = otherMode;
            this.otherModeTwo = otherModeTwo;
        }
    
        @Override
        public String doOtherDataOne() {
            return otherMode.otherData();
        }
    
        @Override
        public String doOtherDataTwo() {
            return otherModeTwo.otherDataTwo();
        }
    }
    
    
    
    //第一个子model的接口类
    public interface IOtherMode {
    
        String otherData();
    }
    
    
    //第二个子model的接口类
    public interface IOtherModeTwo {
    
        String otherDataTwo();
    }
    
    

    以上内容就是我对于MVP架构的理解,分享给大家。初学者应该先把mvp架构的普通用法学会后,再尝试我在文中提到的三种进阶方式,如果直接看的话可能不是特别理解。希望我的这篇文章可以让大家快速的理解mvp,并使用他。

    最后打个广告,本人的github开源项目YzsLib,YzsBaseActivity近期会有重大更新,重构base,兼容mvp架构和mvc架构,欢迎大家star提问奥,放出网址

    https://github.com/yaozs/YzsBaseActivity

    https://github.com/yaozs/YzsLib

    让我们一起共同进步,向资深大牛前进

    相关文章

      网友评论

      • wo叫天然呆:如果功能很多,是不是要创建很多个TestMvpListContract?
      • Troll4it:Troll,这名字有没有觉得很熟悉,哈哈,来个沙发

      本文标题:MVP架构开发,一篇让你从看懂到会使用

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