MVP设计模式

    在Android开发中,随着业务的复杂,代码量的增加,Activity类往往会越来越大,这是因为,在Android中允View和其它线程共存于Activity内。在Activity中同时存在业务逻辑和UI逻辑,不仅会造成Activity的臃肿,还会使代码显得凌乱,后期不好维护。传统的MVC设计模式就存在这样的问题。而新的MVP设计模式会使View层的Activity和Fragment变得非常轻量,让他们唯一的职责就是建立/更新UI和处理用户事件,MVP设计包括三层结构,分别为:View层、Model层、Presenter层。他们关系如下:

  • View 对应于Activity,负责View的绘制以及与用户交互(更新视图的接口,activity实现其接口)
  • Model 依然是业务逻辑和实体模型(javabean,database、Utils、耗时操作,线程等)
  • Presenter 负责完成View于Model间的交互(Model和View之间交互的桥梁,登录,登录失败,成功,清除数据等)

    View与Model并不直接交互,而是使用Presenter作为View与Model之间的桥梁。其中Presenter中同时持有Viwe层以及Model层的Interface的引用,而View层持有Presenter层Interface的引用。当View层某个界面需要展示某些数据的时候,首先会调用Presenter层的某个接口,然后Presenter层会调用Model层请求数据,当Model层数据加载成功之后会调用Presenter层的回调方法通知Presenter层数据加载完毕,最后Presenter层再调用View层的接口将加载后的数据展示给用户。

    现在以加载新闻列表为例,进行详细说明,首先来看看包结构:



一、View层

    1、定义接口

    接口中应该包括View层需要展示的东西,在本例子中需要展示新闻列表,就需要展示加载进度、隐藏加载进度、展示加载消息、展示加载错误四个抽象出来的接口,并且需要View层Activity或者Fragment实现该接口,在接口中进行处理。同时也需要Presenter实现该接口。

    public interface INewsView {
        //展示加载进度
        void showProgress();
        //隐藏加载进度
        void hideProgress();
        //展示加载失败消息
        void showLoadFailMsg();
        //设置Adapter
        void setAdapter();
    }
    2、Activity实现

    Activity/Fragment需要View层的接口,并且重写所有的方法,在对象的方法里面进行具体的实现。由于View层不和Modle层进行交互,所以在setAdapter时候需要mNewsPersenter层提供数据源。

    public class MainActivity extends AppCompatActivity implements INewsView{

        private ProgressBar mProgressBar;
        private TextView mEmptyText;
        private ListView mListView;
        private NewsPersenter mNewsPersenter;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mProgressBar = findViewById(R.id.pb_progress);
            mEmptyText = findViewById(R.id.tv_empty);
            mListView = findViewById(R.id.lv_list);

            //创建Persenter对象,他是View层和Modle层进行交互的桥梁
            mNewsPersenter = new NewsPersenter(this);
            //通过Persenter层开启请求
            mNewsPersenter.requestNesInfo();
        }

        /**
         * 显示进度
         */
        @Override
        public void showProgress() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mProgressBar.setVisibility(View.VISIBLE);
                }
            });
        }

        /**
         * 隐藏进度
         */
        @Override
        public void hideProgress() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mProgressBar.setVisibility(View.INVISIBLE);
                }
            });
        }

        /**
         * 显示错误消息
         */
        @Override
        public void showLoadFailMsg() {
           runOnUiThread(new Runnable() {
               @Override
               public void run() {
                   mEmptyText.setText("加载数据为空……………………");
                   mEmptyText.setVisibility(View.VISIBLE);
                   mListView.setVisibility(View.GONE);
               }
           });
        }

        /**
         * 展示数据列表
         */
        @Override
        public void setAdapter() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    //由于View层不和Modle层进行交互,所以需要mNewsPersenter层提供数据源
                    mListView.setAdapter(new NewsAdapter(MainActivity.this,mNewsPersenter.addNews()));
                }
            });
        }
    }

二、Modle层

    1、定义接口

    Modle层是业务逻辑层,主要用来操作数据,对应新闻列表模块来说这里的数据主要是展示新闻列表,因此就需要一个列表的集合,来存储数据源,因此需要定义一个添加数据的接口。

    public interface INews {
       List<NewsBean> addNews();
    }
    2、实现类NewsImpl
    public class NewsImpl implements INews{

        @Override
        public List<NewsBean> addNews() {
            List<NewsBean>  mList = new ArrayList<>();
            //模拟10条假数据,添加进集合
            for (int i = 0; i < 10; i++) {
                NewsBean news = new NewsBean();
                news.time = "18:0" + i;
                news.title = "第" + i + "个标题";
                news.news = "新闻中心_腾讯网_腾讯新闻";
                mList.add(news);
            }
            return mList;
        }
    }

三、Persenter层

    Persenter层作为连接View层和Modle层的桥梁,需要实现Modle层和View层的接口。

    public class NewsPersenter implements INewsView, INews {

        private NewsImpl mNews;
        private INewsView mINewsView;

        public NewsPersenter(INewsView iNewsView) {
            mNews = new NewsImpl();
            mINewsView = iNewsView;
        }

        /**
         * 供View层调用
         */
        public void requestNesInfo() {
            //为了模拟耗时,所有的操作都在子线程进行
            new Thread() {
                @Override
                public void run() {
                    super.run();
                    showProgress();
                    SystemClock.sleep(3000);
                    hideProgress();
                    addNews();
                    setAdapter();
                    SystemClock.sleep(8000);
                    showLoadFailMsg();
                }
            }.start();
        }


        @Override
        public void showProgress() {
            if (mINewsView != null) {
                mINewsView.showProgress();
            }
        }

        @Override
        public List<NewsBean> addNews() {
            if (mNews != null) {
                return mNews.addNews();
            } else {
                return null;
            }
        }

        @Override
        public void hideProgress() {
            if (mINewsView != null) {
                mINewsView.hideProgress();
            }
        }

        @Override
        public void showLoadFailMsg() {
            if (mINewsView != null) {
                mINewsView.showLoadFailMsg();
            }
        }

        @Override
        public void setAdapter() {
            if (mINewsView != null) {
                mINewsView.setAdapter();
            }
        }
    }
    最后附上Demo地址:https://download.csdn.net/download/yoonerloop/10375853 点击打开链接


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值