zoukankan      html  css  js  c++  java
  • android mvp模式

    Android Mvp 现在被广泛的应用在Android开发项目中,现在我的项目也使用了这种开发设计模式。

    当我们的项目越庞大,复杂,参与的人员越来越多的时候,mcp的优点就展现出来了。

    Mvc与Mvp的区别:

    Mvc模式:

    Activity应该是属于View这一层。而实质上,它既承担了View,同时也包含一些Controller的东西在里面。这对于开发与维护来说不太友好,耦合度大高了。

    MVC模式的结构分为三部分,实体层的Model,视图层的View,以及控制层的Controller。

    • 其中View层其实就是程序的UI界面,用于向用户展示数据以及接收用户的输入

    • 而Model层就是JavaBean实体类,用于保存实例数据

    • Controller控制器用于更新UI界面和数据实例

    Mvp模式:

    把Activity的View和Controller抽离出来就变成了View和Presenter,这就是MVP模式。mvp属于mvc的一个加强版设计模式。

    在Android开发中Activity和fragment都属于view层,负责展现给用户的UI控件,以及接收用户的输入,此外还要负责展现的生命周期的工作。如果在它们代码层在加上业务逻辑判断,就会使的代码看起来臃肿,不利于维护。而且多人进行开发同一个项目时,对于同一界面的增改增多,就会出现冲突,不利于多人开发。所以我们采用mvp模式代替mvc,mvp中view展现层,只负责交互,展现,不负责逻辑判断。Presenter负责所有的逻辑实现,Model负责获取数据用的。

    MVP的好处:

    1.分离了视图逻辑和业务逻辑,降低耦合度。

    2.Activity只负责生命周期和与用户交互的工作,代码比较简洁。

    3.视图逻辑和业务逻辑分别抽象到View和Presenter的接口中去,提高代码的可阅读性。

    4.Presenter抽象成接口,可以实现多个实现类,很方便的进行单元测试。

     其中最重要的有三点:

    Activity 代码变得更加简洁

    相信很多人阅读代码的时候,都是从Activity开始的,对着一个1000+行代码的Activity,看了都觉得难受。

    使用MVP之后,Activity就能瘦身许多了,基本上只有FindView、SetListener以及Init的代码。其他的就是对Presenter的调用,还有对View接口的实现。这种情形下阅读代码就容易多了,而且你只要看Presenter的接口,就能明白这个模块都有哪些业务,很快就能定位到具体代码。Activity变得容易看懂,容易维护,以后要调整业务、删减功能也就变得简单许多。

    方便进行单元测试

    一般单元测试都是用来测试某些新加的业务逻辑有没有问题,如果采用传统的代码风格(习惯性上叫做MV模式,少了P),我们可能要先在Activity里写一段测试代码,测试完了再把测试代码删掉换成正式代码,这时如果发现业务有问题又得换回测试代码,咦,测试代码已经删掉了!好吧重新写吧……

    MVP中,由于业务逻辑都在Presenter里,我们完全可以写一个PresenterTest的实现类继承Presenter的接口,现在只要在Activity里把Presenter的创建换成PresenterTest,就能进行单元测试了,测试完再换回来即可。万一发现还得进行测试,那就再换成PresenterTest吧。

    避免 Activity 的内存泄露

    Android APP 发生OOM的最大原因就是出现内存泄露造成APP的内存不够用,而造成内存泄露的两大原因之一就是Activity泄露(Activity Leak)(另一个原因是Bitmap泄露(Bitmap Leak))。

    Java一个强大的功能就是其虚拟机的内存回收机制,这个功能使得Java用户在设计代码的时候,不用像C++用户那样考虑对象的回收问题。然而,Java用户总是喜欢随便写一大堆对象,然后幻想着虚拟机能帮他们处理好内存的回收工作。可是虚拟机在回收内存的时候,只会回收那些没有被引用的对象,被引用着的对象因为还可能会被调用,所以不能回收。

    Activity是有生命周期的,用户随时可能切换Activity,当APP的内存不够用的时候,系统会回收处于后台的Activity的资源以避免OOM。

    采用传统的MV模式,一大堆异步任务和对UI的操作都放在Activity里面,比如你可能从网络下载一张图片,在下载成功的回调里把图片加载到 Activity 的 ImageView 里面,所以异步任务保留着对Activity的引用。这样一来,即使Activity已经被切换到后台(onDestroy已经执行),这些异步任务仍然保留着对Activity实例的引用,所以系统就无法回收这个Activity实例了,结果就是Activity Leak。Android的组件中,Activity对象往往是在堆(Java Heap)里占最多内存的,所以系统会优先回收Activity对象,如果有Activity Leak,APP很容易因为内存不够而OOM。

    采用MVP模式,只要在当前的Activity的onDestroy里,分离异步任务对Activity的引用,就能避免 Activity Leak。

    说了这么多,没看懂?好吧,我自己都没看懂自己写的,我们还是直接看代码吧。

    上面一张简单的MVP模式的UML图,从图中可以看出,使用MVP,至少需要经历以下步骤:

    1. 创建IPresenter接口,把所有业务逻辑的接口都放在这里,并创建它的实现PresenterCompl(在这里可以方便地查看业务功能,由于接口可以有多种实现所以也方便写单元测试)

    2. 创建IView接口,把所有视图逻辑的接口都放在这里,其实现类是当前的Activity/Fragment

    3. 由UML图可以看出,Activity里包含了一个IPresenter,而PresenterCompl里又包含了一个IView并且依赖了Model。Activity里只保留对IPresenter的调用,其它工作全部留到PresenterCompl中实现

    4. Model并不是必须有的,但是一定会有View和Presenter

    通过上面的介绍,MVP的主要特点就是把Activity里的许多逻辑都抽离到View和Presenter接口中去,并由具体的实现类来完成。这种写法多了许多IView和IPresenter的接口,在某种程度上加大了开发的工作量,刚开始使用MVP的小伙伴可能会觉得这种写法比较别扭,而且难以记住。其实一开始想太多也没有什么卵用,只要在具体项目中多写几次,就能熟悉MVP模式的写法,理解TA的意图,以及享♂受其带来的好处。

        Talk is cheap, let me show you the code!

    1.我们初始化初始化接口BaseView,方法为向activity显示的回调方法。

    2.初始化接口Presenter类,用户处理业务逻辑的抽象类。

    3.初始化接口Contract类,用来连接接口View和接口Presenter的连接类

    4.Presenter处理业务逻辑的类的具体实现

    /**
     * 作为view与Model交互的中间纽带,处理与用户交互负责的逻辑
     */
    
    public class RecommendPresenter implements RecommendContract.Presenter{
    
        private RecommendModel mModel;// 访问网络的Model
    
        private RecommendContract.View mView;// 负责activity的回调。
    
        public RecommendPresenter(RecommendContract.View view) {
            this.mView = view;
            this.mModel = new RecommendModel();
        }
    
        @Override
        public void requestDatas() {
            mView.showLodading();// 通知弹出加载对话框回调
            // 访问网络获取 推送  数据的接口。
            mModel.getApps(new Callback<PageBean<AppInfo>>() {
                @Override
                public void onResponse(Call<PageBean<AppInfo>> call, Response<PageBean<AppInfo>> response) {
    
                    if(response !=null){
                        // 返回数据回调
                        mView.showResult(response.body().getDatas());
                    }
                    else{
                        // 访问数据为空的回调
                        mView.showNodata();
                    }
                        // 关闭弹出的加载的对话框
                    mView.dimissLoading();
    
                }
    
                @Override
                public void onFailure(Call<PageBean<AppInfo>> call, Throwable t) {
                    // 关闭加载对话框回调
                    mView.dimissLoading();
                    // 弹出错误选择框
                    mView.showError(t.getMessage());
    
                }
            });
    
    
        }
    }

    5.Activity的具体实现

    /**
    * 与用户展示的activity或fragment的实现。
    */
    public class RecommendFragment extends Fragment implements RecommendContract.View {
    
        @BindView(R.id.recycle_view)
        RecyclerView mRecyclerView;
    
    
        private ProgressDialog mMProgressDialog;
        private RecommendPresenter mMPredenter;
        private RecomendAppAdatper mAdatper;
    
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
            View mView = inflater.inflate(R.layout.fragment_recomend, container, false);
            ButterKnife.bind(this, mView);
            mMProgressDialog = new ProgressDialog(getActivity());// 加载框 初始化
            mMPredenter = new RecommendPresenter(this);
            isCreateView = true;
            return mView;
        }
    
       
    
        private void initRecycleView(List<AppInfo> datas) {
            //为RecyclerView设置布局管理器
            mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
            //为RecyclerView设置分割线(这个可以对DividerItemDecoration进行修改,自定义)
            mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.HORIZONTAL_LIST));
            //动画
            mRecyclerView.setItemAnimator(new DefaultItemAnimator());
            mAdatper = new RecomendAppAdatper(getActivity(), datas);
            mRecyclerView.setAdapter(mAdatper);
        }
    
    
        @Override
        public void showResult(List<AppInfo> datas) {
            initRecycleView(datas);
        }
    
        @Override
        public void showNodata() {
            Toast.makeText(getActivity(), "暂时无数据,请吃完饭再来", Toast.LENGTH_LONG).show();
        }
    
        @Override
        public void showError(String msg) {
            Toast.makeText(getActivity(), "服务器开小差了:" + msg, Toast.LENGTH_LONG).show();
        }
    
        @Override
        public void showLodading() {
            mMProgressDialog.show();
        }
    
        @Override
        public void dimissLoading() {
            if (mMProgressDialog.isShowing()) {
                mMProgressDialog.dismiss();
            }
        }
    
    }
    

      这样就架构出来了MVP模式代码。

       

  • 相关阅读:
    Qt源文件和ui文件的关系
    使用moveToThread线程并正确回收内存的方式
    mysql设置某字段不可重复
    使用curl创建简单的性能监控工具
    你是不是那个带不动的队友
    这样的面试你能通过吗
    浅谈测试观
    自动化测试如何准备测试数据
    关于双十二崩盘的一些思考
    浅谈测试环境
  • 原文地址:https://www.cnblogs.com/lixiangyang521/p/6707662.html
Copyright © 2011-2022 走看看