mvp 订阅
美国职业篮球联赛最有价值球员奖(National Basketball Association Most Valuable Player Award ,简称MVP)是一个自1955-1956赛季以来每年对美国职业篮球联赛(NBA)常规赛中全场表现最佳的球员所颁发的一个奖项。为纪念NBA首位总裁莫里斯·波多罗夫,于是将MVP奖杯命名为“莫里斯·波多罗夫杯“。 展开全文
美国职业篮球联赛最有价值球员奖(National Basketball Association Most Valuable Player Award ,简称MVP)是一个自1955-1956赛季以来每年对美国职业篮球联赛(NBA)常规赛中全场表现最佳的球员所颁发的一个奖项。为纪念NBA首位总裁莫里斯·波多罗夫,于是将MVP奖杯命名为“莫里斯·波多罗夫杯“。
信息
外文名
National Basketball Association Most Valuable Player Award
奖杯名称
莫里斯·波多罗夫杯
出    处
NBA
中文名
美国职业篮球联赛最有价值球员奖
开始时间
1955-56赛季
美国职业篮球联赛最有价值球员奖奖项信息
NBA常规赛结束后就会进行最有价值球员(MVP)的投票评选工作。直到1979-1980赛季,最初的MVP奖项都是由NBA球员投票评选出的。然而从1980-1981赛季开始,由美国和加拿大的体育记者和电视评论员投票决定MVP奖项的最终归属。每一位评委分别投票选出自己心目中最好的第一到第五位的球员。球员每获得一张第一位的选票将获得10分,第二位选票获得7分,第三位选票获得5分,第四位选票3分,第五位选票获得1分。从2010年开始,将有一张选票是由球迷通过网络投票评选出的,得票最多的球员将获得这张选票。 [1]  入选奈·史密斯篮球名人纪念堂的卡里姆·阿布杜尔-贾巴尔曾6次获得这一奖项。 [2]  比尔·拉塞尔和迈克尔·乔丹均5次获得该奖, [1]  而威尔特·张伯伦、勒布朗·詹姆斯则4次获得该奖。另外,名人堂球员摩西·马龙、拉里·伯德和埃尔文·约翰逊(“魔术师”约翰逊)都3次获得该奖;鲍勃·佩蒂特、卡尔·马龙、史蒂夫·纳什、蒂姆·邓肯、斯蒂芬·库里均2次斩获该奖项。 [1]  2014年NBA最有价值球员奖授予了凯文·杜兰特,他获得了125张第一名选票中的119张。 [3]  2016年斯蒂芬·库里成为NBA历史上首个全票当选MVP的球员。只有两位球员在新秀赛季就拿到了这个奖,分别是1959-1960赛季的威尔特·张伯伦,1968-1969赛季的韦斯·昂塞尔德。 [4]  获得该奖而非美国出生的球员有尼日利亚的哈基姆·奥拉朱旺 [5]  、美属维尔京群岛的蒂姆·邓肯、加拿大的史蒂夫·纳什 [6]  、德国的德克·诺维茨基、希腊的扬尼斯·安特托昆博。邓肯其实是美国公民,不过由于他并不是在美国的50个州或者华盛顿出生,所以他被看作是一名国际球员。比尔.拉塞尔,威尔特.张伯伦,拉里.伯德都曾连续三年获得MVP奖项。
收起全文
精华内容
下载资源
问答
  • MVP

    2019-03-18 08:01:30
    OKHttp MVP M层接口 MVP M层类 MVP P层接口 MVP P层类 MVP V层接口 shopAdapter MainActivity 页面

    OKHttp

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    MVP M层接口

    在这里插入图片描述

    MVP M层类
    在这里插入图片描述

    MVP P层接口

    在这里插入图片描述
    MVP P层类
    在这里插入图片描述
    MVP V层接口
    在这里插入图片描述
    shopAdapter

    在这里插入图片描述

    在这里插入图片描述
    MainActivity 页面
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • mvp

    2016-03-22 10:18:51
    presenters/** * Created by lyl on 2016/3/17. ...public abstract class MVPBasePresenter<V extends MVPView> implements MVPPresenter<V> { private WeakReference<V> viewRef; public void attachView

    presenters

    /**
     * Created by lyl on 2016/3/17.
     */
    public abstract class MVPBasePresenter<V extends MVPView> implements MVPPresenter<V> {
        private WeakReference<V> viewRef;
    
        public void attachView(V view) {
            viewRef = new WeakReference<V>(view);
        }
    
        protected V getView() {
            return viewRef.get();
        }
    
        protected boolean isViewAttached() {
            return viewRef != null && viewRef.get() != null;
        }
    
        public void detachView() {
            if (viewRef != null) {
                viewRef.clear();
                viewRef = null;
            }
        }
    }
    
    
    -------------------------------------------------------------------------------------
    
    
    /**
     * Created by lyl on 2016/3/17.
     */
    public interface MVPPresenter<V extends MVPView> {
        void attachView(V view);
        void detachView();
    }
    
    -------------------------------------------------------------------------------------
    /**
     * Created by lyl on 2016/3/17.
     */
    public interface OrderShowPresenter extends MVPPresenter<IOrderShow> {
    
        void login();
    
        void linkSocket();
    
    }
    -------------------------------------------------------------------------------------
    /**
     * Created by lyl on 2016/3/17.
     */
    public interface OrderShowPresenter extends MVPPresenter<IOrderShow> {
    
        void login();
    
        void linkSocket();
    
    }
    /**
     * Created by lyl on 2016/3/17.
     */
    public class OrderShowPresenterImpl extends MVPBasePresenter<IOrderShow> implements OrderShowPresenter {
    
        @Override
        public void login() {
             getView().ShowOrderInfo();
        }
    }
    -------------------------------------------------------------------------------------

    views

    /**
     * Created by lyl on 2016/3/17.
     */
    public abstract class MvpBaseActivity<P extends MVPPresenter> extends Activity implements MVPView {
    
        protected P presenter;
        protected abstract P createPresenter();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            presenter = createPresenter();
            if (presenter == null) {
                throw new NullPointerException("Presenter is null! Do you return null in createPresenter()?");
            }
            presenter.attachView(this);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            presenter.detachView();
        }
    
        @Override
        public Context getContext() {
            return this;
        }
    
    }
    
    -------------------------------------------------------------------------------------
    /**
     * Root class for view classes
     */
    public interface MVPView {
        android.content.Context getContext();
    }
    -------------------------------------------------------------------------------------
    /**
     * Created by lyl on 2016/3/17.
     */
    public interface IOrderShow extends MVPView {
    
        void ShowOrderInfo(List<OrderPanding> listPanding,List<OrderPanding> listProcess,List<OrderPanding> listSuccess);
    }
    

    activity

    public class MainActivity extends MvpBaseActivity<OrderShowPresenter> implements IOrderShow {
    
        @Override
        protected OrderShowPresenter createPresenter() {
            return new OrderShowPresenterImpl();
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            presenter.login();
        }
    
        @Override
        public void ShowOrderInfo() {}
    }
    展开全文
  • 浅谈 MVP in Android

    万次阅读 多人点赞 2015-06-23 09:11:49
    对于MVP(Model View Presenter),大多数人都能说出一二:“MVC的演化版本”,“让Model和View完全解耦”等等。本篇博文仅是为了做下记录,提出一些自己的看法,和帮助大家如何针对一个Activity页面去编写针对MVP...

    转载请标明出处:
    http://blog.csdn.net/lmj623565791/article/details/46596109
    本文出自:【张鸿洋的博客】

    一、概述

    对于MVP(Model View Presenter),大多数人都能说出一二:“MVC的演化版本”,“让Model和View完全解耦”等等。本篇博文仅是为了做下记录,提出一些自己的看法,和帮助大家如何针对一个Activity页面去编写针对MVP风格的代码。

    对于MVP,我的内心有一个问题:

    为何这个模式出来后,就能被广大的Android的程序员接受呢?

    问了些程序员,他们对于MVP的普遍的认识是:“代码很清晰,不过增加了很多类”。我在第一次看到MVP的时候,看了一个demo,看完以后觉得非常nice(但是回过头来,自己想个例子写,就头疼写不出来,当然这在后文会说)。nice的原因还是因为,这个模式的确让代码的清晰度有了很大的提升。

    那么,提升一般都是对比出来的,回顾下,没有应用MVP的代码结构。很多人说明显是MVC么:

    • View:对应于布局文件
    • Model:业务逻辑和实体模型
    • Controllor:对应于Activity

    看起来的确像那么回事,但是细细的想想这个View对应于布局文件,其实能做的事情特别少,实际上关于该布局文件中的数据绑定的操作,事件处理的代码都在Activity中,造成了Activity既像View又像Controller(当然了Data-Binder的出现,可能会让View更像View吧)。这可能也就是为何,在该文中有一句这样的话:

    Most of the modern Android applications just use View-Model architecture,everything is connected with Activity.

    而当将架构改为MVP以后,Presenter的出现,将Actvity视为View层,Presenter负责完成View层与Model层的交互。现在是这样的:

    • View 对应于Activity,负责View的绘制以及与用户交互
    • Model 依然是业务逻辑和实体模型
    • Presenter 负责完成View于Model间的交互

    ok,先简单了解下,文中会有例子到时候可以直观的感受下。

    小总结下,也就是说,之所以让人觉得耳目一新,是因为这次的跳跃是从并不标准的MVCMVP的一个转变,减少了Activity的职责,简化了Activity中的代码,将复杂的逻辑代码提取到了Presenter中进行处理。与之对应的好处就是,耦合度更低,更方便的进行测试。借用两张图(出自:该文),代表上述的转变:

    转变为:

    二、MVP 与 MVC 区别

    ok,上面说了一堆理论,下面我们还是需要看一看MVC与MVP的一个区别,请看下图(来自:本文):

    其实最明显的区别就是,MVC中是允许Model和View进行交互的,而MVP中很明显,Model与View之间的交互由Presenter完成。还有一点就是Presenter与View之间的交互是通过接口的(代码中会体现)。

    还有一堆概念性的东西,以及优点就略了,有兴趣自行百度。下面还是通过一些简单的需求来展示如何编写MVP的demo。

    三、Simple Login Demo

    效果图:

    看到这样的效果,先看下完工后的项目结构:

    ok,接下来开始一步一步的编写思路。

    (一)Model

    首先实体类User不用考虑这个肯定有,其次从效果图可以看到至少有一个业务方法login(),这两点没什么难度,我们首先完成:

    package com.zhy.blogcodes.mvp.bean;
    
    /**
     * Created by zhy on 15/6/18.
     */
    public class User
    {
        private String username ;
        private String password ;
    
        public String getUsername()
        {
            return username;
        }
    
        public void setUsername(String username)
        {
            this.username = username;
        }
    
        public String getPassword()
        {
            return password;
        }
    
        public void setPassword(String password)
        {
            this.password = password;
        }
    }
    
    
    package com.zhy.blogcodes.mvp.biz;
    
    /**
     * Created by zhy on 15/6/19.
     */
    public interface IUserBiz
    {
        public void login(String username, String password, OnLoginListener loginListener);
    }
    
    
    
    package com.zhy.blogcodes.mvp.biz;
    
    import com.zhy.blogcodes.mvp.bean.User;
    
    /**
     * Created by zhy on 15/6/19.
     */
    public class UserBiz implements IUserBiz
    {
    
        @Override
        public void login(final String username, final String password, final OnLoginListener loginListener)
        {
            //模拟子线程耗时操作
            new Thread()
            {
                @Override
                public void run()
                {
                    try
                    {
                        Thread.sleep(2000);
                    } catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                    //模拟登录成功
                    if ("zhy".equals(username) && "123".equals(password))
                    {
                        User user = new User();
                        user.setUsername(username);
                        user.setPassword(password);
                        loginListener.loginSuccess(user);
                    } else
                    {
                        loginListener.loginFailed();
                    }
                }
            }.start();
        }
    }
    
    
    package com.zhy.blogcodes.mvp.biz;
    
    import com.zhy.blogcodes.mvp.bean.User;
    
    /**
     * Created by zhy on 15/6/19.
     */
    public interface OnLoginListener
    {
        void loginSuccess(User user);
    
        void loginFailed();
    }
    
    

    实体类不用说,至于业务类,我们抽取了一个接口,一个实现类这也很常见~~login方法,一般肯定是连接服务器的,是个耗时操作,所以我们开辟了子线程,Thread.sleep(2000)模拟了耗时,由于是耗时操作,所以我们通过一个回调接口来通知登录的状态。

    其实这里还是比较好写的,因为和传统写法没区别。

    (二) View

    上面我们说过,Presenter与View交互是通过接口。所以我们这里需要定义一个ILoginView,难点就在于应该有哪些方法,我们看一眼效果图:

    可以看到我们有两个按钮,一个是login,一个是clear;

    login说明了要有用户名、密码,那么对应两个方法:

    
        String getUserName();
    
        String getPassword();

    再者login是个耗时操作,我们需要给用户一个友好的提示,一般就是操作ProgressBar,所以再两个:

        void showLoading();
    
        void hideLoading();

    login当然存在登录成功与失败的处理,我们主要看成功我们是跳转Activity,而失败可能是去给个提醒:

        void toMainActivity(User user);
    
        void showFailedError();

    ok,login这个方法我们分析完了~~还剩个clear那就简单了:

        void clearUserName();
    
        void clearPassword();

    综上,接口完整为:

    package com.zhy.blogcodes.mvp.view;
    
    import com.zhy.blogcodes.mvp.bean.User;
    
    /**
     * Created by zhy on 15/6/19.
     */
    public interface IUserLoginView
    {
        String getUserName();
    
        String getPassword();
    
        void clearUserName();
    
        void clearPassword();
    
        void showLoading();
    
        void hideLoading();
    
        void toMainActivity(User user);
    
        void showFailedError();
    
    }

    有了接口,实现就太好写了~~~

    总结下,对于View的接口,去观察功能上的操作,然后考虑:

    • 该操作需要什么?(getUserName, getPassword)
    • 该操作的结果,对应的反馈?(toMainActivity, showFailedError)
    • 该操作过程中对应的友好的交互?(showLoading, hideLoading)

    下面贴一下我们的View的实现类,哈,其实就是Activity,文章开始就说过,MVP中的View其实就是Activity。

    package com.zhy.blogcodes.mvp;
    
    import android.os.Bundle;
    import android.support.v7.app.ActionBarActivity;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ProgressBar;
    import android.widget.Toast;
    
    import com.zhy.blogcodes.R;
    import com.zhy.blogcodes.mvp.bean.User;
    import com.zhy.blogcodes.mvp.presenter.UserLoginPresenter;
    import com.zhy.blogcodes.mvp.view.IUserLoginView;
    
    public class UserLoginActivity extends ActionBarActivity implements IUserLoginView
    {
    
    
        private EditText mEtUsername, mEtPassword;
        private Button mBtnLogin, mBtnClear;
        private ProgressBar mPbLoading;
    
        private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this);
    
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_user_login);
    
            initViews();
        }
    
        private void initViews()
        {
            mEtUsername = (EditText) findViewById(R.id.id_et_username);
            mEtPassword = (EditText) findViewById(R.id.id_et_password);
    
            mBtnClear = (Button) findViewById(R.id.id_btn_clear);
            mBtnLogin = (Button) findViewById(R.id.id_btn_login);
    
            mPbLoading = (ProgressBar) findViewById(R.id.id_pb_loading);
    
            mBtnLogin.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    mUserLoginPresenter.login();
                }
            });
    
            mBtnClear.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    mUserLoginPresenter.clear();
                }
            });
        }
    
    
        @Override
        public String getUserName()
        {
            return mEtUsername.getText().toString();
        }
    
        @Override
        public String getPassword()
        {
            return mEtPassword.getText().toString();
        }
    
        @Override
        public void clearUserName()
        {
            mEtUsername.setText("");
        }
    
        @Override
        public void clearPassword()
        {
            mEtPassword.setText("");
        }
    
        @Override
        public void showLoading()
        {
            mPbLoading.setVisibility(View.VISIBLE);
        }
    
        @Override
        public void hideLoading()
        {
            mPbLoading.setVisibility(View.GONE);
        }
    
        @Override
        public void toMainActivity(User user)
        {
            Toast.makeText(this, user.getUsername() +
                    " login success , to MainActivity", Toast.LENGTH_SHORT).show();
        }
    
        @Override
        public void showFailedError()
        {
            Toast.makeText(this,
                    "login failed", Toast.LENGTH_SHORT).show();
        }
    }

    对于在Activity中实现我们上述定义的接口,是一件很容易的事,毕竟接口引导我们去完成。

    最后看我们的Presenter。

    (三)Presenter

    Presenter是用作Model和View之间交互的桥梁,那么应该有什么方法呢?

    其实也是主要看该功能有什么操作,比如本例,两个操作:login和clear。

    package com.zhy.blogcodes.mvp.presenter;
    
    import android.os.Handler;
    
    import com.zhy.blogcodes.mvp.bean.User;
    import com.zhy.blogcodes.mvp.biz.IUserBiz;
    import com.zhy.blogcodes.mvp.biz.OnLoginListener;
    import com.zhy.blogcodes.mvp.biz.UserBiz;
    import com.zhy.blogcodes.mvp.view.IUserLoginView;
    
    
    /**
     * Created by zhy on 15/6/19.
     */
    public class UserLoginPresenter
    {
        private IUserBiz userBiz;
        private IUserLoginView userLoginView;
        private Handler mHandler = new Handler();
    
        public UserLoginPresenter(IUserLoginView userLoginView)
        {
            this.userLoginView = userLoginView;
            this.userBiz = new UserBiz();
        }
    
        public void login()
        {
            userLoginView.showLoading();
            userBiz.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener()
            {
                @Override
                public void loginSuccess(final User user)
                {
                    //需要在UI线程执行
                    mHandler.post(new Runnable()
                    {
                        @Override
                        public void run()
                        {
                            userLoginView.toMainActivity(user);
                            userLoginView.hideLoading();
                        }
                    });
    
                }
    
                @Override
                public void loginFailed()
                {
                    //需要在UI线程执行
                    mHandler.post(new Runnable()
                    {
                        @Override
                        public void run()
                        {
                            userLoginView.showFailedError();
                            userLoginView.hideLoading();
                        }
                    });
    
                }
            });
        }
    
        public void clear()
        {
            userLoginView.clearUserName();
            userLoginView.clearPassword();
        }
    
    
    
    }
    

    注意上述代码,我们的presenter完成二者的交互,那么肯定需要二者的实现类。大致就是从View中获取需要的参数,交给Model去执行业务方法,执行的过程中需要的反馈,以及结果,再让View进行做对应的显示。

    ok,拿到一个例子经过上述的分解基本就能完成。以上纯属个人见解,欢迎讨论和吐槽~ have a nice day ~。

    源码点击下载

    微信公众号:hongyangAndroid
    (欢迎关注,第一时间推送博文信息)

    参考资料

    展开全文
  • MVC、MVP、MVVM,我到底该怎么选?

    万次阅读 多人点赞 2018-07-03 20:42:29
    本文由玉刚说写作平台提供写作赞助 原作者:AndroFarmer 版权声明:本文版权归微信...比如看了好多篇文章都搞不懂MVC到底是个啥本来想写个MVP写着写着就变成MVC了,到底Databing和MVVM之间有啥见不得人的关系...

    本文由玉刚说写作平台提供写作赞助

    原作者:AndroFarmer

    版权声明:本文版权归微信公众号玉刚说所有,未经许可,不得以任何形式转载

    前言

    MVC、MVP、MVVM是我们工作和面试中都比较重要的一块,但很多时候我们却有点迷惑。比如看了好多篇文章都搞不懂MVC到底是个啥本来想写个MVP写着写着就变成MVC了,到底Databing和MVVM之间有啥见不得人的关系。本篇文章主要从发展的角度来介绍,如mvp,mvvm的出现都是为了解决前者的哪些问题。如果你有同样的疑问,本篇文章可能会给你带来一点收获。但是架构和设计模式相对来说不是那么容易捉摸透的东西,很多需要经过实践才能体会,另外由于本人水平有限,如果写的不对或者不严谨的地方,请不要打我。

    MVC

    可能由于MVP、MVVM的兴起,MVC在android中的应用变得越来越少了,但MVC是基础,理解好MVC才能更好的理解MVP,MVVM。因为后两种都是基于MVC发展而来的。

    1、MVC眼花缭乱设计图

    我们从网上搜索mvc相关资料时,如果你多看几篇文章的话可能会发现,好像他们介绍的设计图都不太一样,这里罗列了大部分的设计图
    mvc1.png
    mvc2.png
    mvc3.png
    mvc4.png

    2、MVC设计图解释

    到底上面列出的设计图哪个才是对的。其实都是对的。为什么这么说呢,这得从mvc的发展说起。
    MVC框架模式最早由Trygve Reenskaug 于1978年在Smalltalk-80系统上首次提出。经过了这么多年的发展,当然会演变出不同的版本,但核心没变依旧还是三层模型Model-View-Control。

    3、MVC三层之间的关系

    箭头→代表的是一种事件流向,并不一定要持有对方,比如上图中model→view的事件流向,view可以通过注册监听器的形式得到model发来的事件。在设计中model view controller之间如果要通讯,尽量设计成不直接持有,这样方便复用。也符合mvc的设计初衷
    在android中三者对应的关系如下:

    视图层(View)
    对应于xml布局文件和java代码动态view部分

    控制层(Controller)
    MVC中Android的控制层是由Activity来承担的,Activity本来主要是作为初始化页面,展示数据的操作,但是因为XML视图功能太弱,所以Activity既要负责视图的显示又要加入控制逻辑,承担的功能过多。

    模型层(Model)
    针对业务模型,建立的数据结构和相关的类,它主要负责网络请求,数据库处理,I/O的操作。

    由于android中有个god object的存在activity,再加上android中xml布局的功能性太弱,所以activity承担了绝大部分的工作。所以在android中mvc更像是这种形式:

    因为activity扮演了controller和view的工作,所以controller和view不太好彻底解耦,但是在一定程度上我们还是可以解耦的。
    Talk is cheap. Show me the code. 扯了这么多,我们来看点代码。

    4、MVC sample

    通过代码来看下,mvc在android中的实现

    结构很简单,这里介绍下其中的关键代码

    public interface BaseModel {
        void onDestroy();
    }
    

    BaseModel顾名思义就是所有业务逻辑model的父类,这里的onDestroy()方法用于跟activity或者fragment生命周期同步,在destroy做一些销毁操作

    public interface Callback1<T> {
        void onCallBack(T t);
    }
    public interface Callback2<T,P> {
        void onCallBack(T t,P p);
    }
    

    Callback是根据View或者Controller调用Model时回调的参数个数选择使用

    public class SampleModel  implements BaseModel{
    
        public void  getUserInfo(String uid,Callback1<UserInfo> callback)
        {
    
            UserInfo userInfo= new HttpUtil<UserInfo>().get(uid);
            callback.onCallBack(userInfo);
    
        }
    
        @Override
        public void onDestroy() {
    
        }
    
        public class UserInfo
        {
            private int age;
            private String name;
    
            public int getAge() {
                return age;
            }
    
            public void setAge(int age) {
                this.age = age;
            }
    
            public String getName() {
                return name;
            }
    
            public void setName(String name) {
                this.name = name;
            }
        }
    }
    

    SampleModel是我们业务逻辑的具体实现

    public class SampleActivity extends AppCompatActivity {
        private SampleModel sampleModel;
        Button button;
        EditText textView;
        TextView tvAge,tvName;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_sample);
            sampleModel=new SampleModel();
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    getUserInfo(textView.getText().toString());
                }
            });
    
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            sampleModel.onDestroy();
        }
    
        /**
         * 获取用户信息
         * @param uid
         */
        private void getUserInfo(String uid)
        {
            sampleModel.getUserInfo(uid, new Callback1<SampleModel.UserInfo>() {
                @Override
                public void onCallBack(SampleModel.UserInfo userInfo) {
                    setDataToView(userInfo);
                }
            });
        }
    
        /**
         * 设置用户信息到view
         */
        private void setDataToView(SampleModel.UserInfo userInfo)
        {
            tvAge.setText(userInfo.getAge());
            tvName.setText(userInfo.getName());
        }
    
    }
    
    
    

    前面说了Activity充当View和Controller,但是我们依然要区分到底哪一部分是View的操作,哪一部分是Controller的操作。
    我们分析下事件的流向
    button点击事件的触发:View→Controller
    获取用户信息事件的触发:Controller→Model
    绑定用户信息到View:Controller→View
    至此MVC就讲完了

    5、MVC总结

    我们这里根据sample来总结下:

    • 具有一定的分层,model彻底解耦,controller和view并没有解耦
    • 层与层之间的交互尽量使用回调或者去使用消息机制去完成,尽量避免直接持有
    • controller和view在android中无法做到彻底分离,但在代码逻辑层面一定要分清
    • 业务逻辑被放置在model层,能够更好的复用和修改增加业务

    MVP

    1、MVP说明

    MVP跟MVC很相像,文章开头列出了很多种MVC的设计图,所以根据MVC的发展来看,我们把MVP当成MVC来看也不为过,因为MVP也是三层,唯一的差别是Model和View之间不进行通讯,都是通过Presenter完成。
    前面介绍MVC的时候提到了算是致命缺点吧,在android中由于activity(god object)的存在,Controller和View很难做到完全解耦。但在MVP中就可以很好的解决这个问题
    看下MVP的设计图:
    mvp.png
    一般情况下就这两种

    2、MVP Sample

    依然延续MVC的例子,修改下结构通过MVP去实现,看下项目代码结构:

    callback,http包下内容基本一致,主要看下不同的地方

    public interface BasePresenter {
        void onDestroy();
    }
    

    BasePresenter类似于MVC中的BaseModel,主要负责业务逻辑的实现。我们这里没有把业务逻辑放在Model里去实现,当然把主要业务逻辑放在Model中去实现也是可以的。google的MVP实现方案是把业务逻辑放在presenter中,弱化Model,我们这里也是这样做的。

    public interface BaseView<P extends BasePresenter> {
        void setPresenter(P presenter);
    }
    

    BaseView是所有View的父类,将android中的view抽象话出来,只有跟view相关的操作都由baseView的实现类去完成。

    public class SampleContract {
        public static class Presenter implements BasePresenter
        {
            public void  getUserInfo(String uid,Callback1<SampleModel.UserInfo> callback)
            {
                SampleModel.UserInfo userInfo= new HttpUtil<SampleModel.UserInfo>().get(uid);
                callback.onCallBack(userInfo);
            }
    
            @Override
            public void onDestroy() {
    
            }
        }
        public interface View extends BaseView<Presenter>
        {
             void setDataToView(SampleModel.UserInfo userInfo);
        }
    }
    

    Contract 契约类这是Google MVP与其他实现方式的又一个不同,契约类用于定义同一个界面的view的接口和presenter的具体实现。好处是通过规范的方法命名和注释可以清晰的看到整个页面的逻辑。

    public class SampleActivity extends AppCompatActivity implements SampleContract.View{
        private  SampleContract.Presenter mPresenter;
        Button button;
        EditText textView;
        TextView tvAge,tvName;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_sample);
            setPresenter(new SampleContract.Presenter());
    
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    mPresenter.getUserInfo(textView.getText().toString(), new Callback1<SampleModel.UserInfo>() {
                        @Override
                        public void onCallBack(SampleModel.UserInfo userInfo) {
                            setDataToView(userInfo);
                        }
                    });
                }
            });
    
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            mPresenter.onDestroy();
        }
    
        @Override
        public void setDataToView(SampleModel.UserInfo userInfo) {
            tvAge.setText(userInfo.getAge());
            tvName.setText(userInfo.getName());
        }
    
    
        @Override
        public void setPresenter(SampleContract.Presenter presenter) {
            mPresenter=presenter;
        }
    }
    

    这里的SampleActivity实现了SampleContract.View只是作为View存在的。虽然看起来,跟MVC中的实现很相似,但却有本质的区别。mPresenter为Model和View之间交互的桥梁。Presenter跟View相互持有,这里SampleActivity实现了SampleContract.View,mPresenter作为SampleActivity的成员变量,SampleActivity当然持有mPresenter,由于mPresenter是非静态的成员标量,因此默认持有SampleActivity的引用。

    3、MVP总结

    通过引入接口BaseView,让相应的视图组件如Activity,Fragment去实现BaseView,实现了视图层的独立,通过中间层Preseter实现了Model和View的完全解耦。MVP彻底解决了MVC中View和Controller傻傻分不清楚的问题,但是随着业务逻辑的增加,一个页面可能会非常复杂,UI的改变是非常多,会有非常多的case,这样就会造成View的接口会很庞大。

    MVVM

    1、MVVM说明

    MVP中我们说过随着业务逻辑的增加,UI的改变多的情况下,会有非常多的跟UI相关的case,这样就会造成View的接口会很庞大。而MVVM就解决了这个问题,通过双向绑定的机制,实现数据和UI内容,只要想改其中一方,另一方都能够及时更新的一种设计理念,这样就省去了很多在View层中写很多case的情况,只需要改变数据就行。
    先看下MVVM设计图:
    mvvm.png
    一般情况下就这两种情况,这看起来跟MVP好像没啥差别,其实区别还是挺大的,在MVP中View和presenter要相互持有,方便调用对方,而在MVP中 View和ViewModel通过Binding进行关联,他们之前的关联处理通过DataBinding完成。

    2、MVVM与DataBinding的关系

    一句话表述就是,MVVM是一种思想,DataBinding是谷歌推出的方便实现MVVM的工具。在google推出DataBinding之前,因为xml layout功能较弱,想实现MVVM非常困难。而DataBinding的出现可以让我们很方便的实现MVVM。

    3、DataBinding简介

    DataBinding是实现视图和数据双向绑定的工具,这里简单介绍下基本用法,详细用法可以参照官方:https://developer.android.com/topic/libraries/data-binding/
    启用DataBinding,只需要在gradle文件中添加如下代码:

    android {    
        dataBinding{
            enabled true
        }
    }
    

    通过DataBindingUtil可以动态生成一个ViewDataBinding的子类,类名以layout文件名大写加Binding组成,如:

    ActivitySampleMvvmBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_sample_mvvm);
    

    在layout中需要我们配置,每个控件绑定的实体对象,以layout进行包裹,data中配置变量名和类型,通过@{}或@={}的方式进行引用,其中@={}的方式表示双向绑定。目前支持双向绑定的控件如下:

    AbsListView android:selectedItemPosition
    CalendarView android:date
    CompoundButton android:checked
    DatePicker android:year, android:month, android:day
    NumberPicker android:value
    RadioGroup android:checkedButton
    RatingBar android:rating
    SeekBar android:progress
    TabHost android:currentTab
    TextView android:text
    TimePicker android:hour, android:minute

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
        <data >
            <variable
                name="user"
                type="com.androfarmer.mvvm.model.SampleModel.UserInfo">
            </variable>
        </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@={user.name}"
            />
        <TextView
            android:id="@+id/tv_age"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@={user.age+``}"
            />
    
    </LinearLayout>
    </layout>
    
    

    以上为具体在xml的用法展示

    public static class UserInfo  extends BaseObservable
        {
            private int age;
            private String name;
    
            @Bindable
            public int getAge() {
                return age;
            }
    
            public void setAge(int age) {
                this.age = age;
                notifyPropertyChanged(BR.age);
            }
    
            @Bindable
            public String getName() {
                return name;
            }
    
            public void setName(String name) {
                this.name = name;
                notifyPropertyChanged(BR.name);
            }
        }
    

    为了实现双向绑定还需要对数据实体类做处理,继承BaseObservable,对读写方法做@Bindable和notifyPropertyChanged处理。还可以直接使用官方提供的泛型可观察对象 ObservableField,比如:
    private ObservableField name=new ObservableField<>();

    4、MVVM Sample

    MVVM中跟MVP中一样,将三层划分的很清楚,Activity和xml layout充当View,ViewModel处理业务逻辑以及获取数据,弱化Model。
    很多代码跟前面类似,这里只列出核心代码,ViewModel层的

    public interface BaseViewModel {
        void onDestroy();
    }
    
    public abstract class AbstractViewModel<T extends ViewDataBinding> implements BaseViewModel {
        public T mViewDataBinding;
        public AbstractViewModel(T viewDataBinding)
        {
            this.mViewDataBinding=viewDataBinding;
        }
    
        @Override
        public void onDestroy() {
            mViewDataBinding.unbind();
        }
    }
    
    public class SampleViewModel extends AbstractViewModel<ActivitySampleMvvmBinding> {
    
        public SampleViewModel(ActivitySampleMvvmBinding viewDataBinding) {
            super(viewDataBinding);
        }
    
        public  void getUserInfo(String uid, Callback1<SampleModel.UserInfo> callback)
        {
            //从网络或缓存获取信息
            SampleModel.UserInfo userInfo=new SampleModel.UserInfo();
            userInfo.setName("tom");
            userInfo.setAge(18);
            callback.onCallBack(userInfo);
        }
    }
    

    ViewMode层主要处理业务逻辑和获取数据,mViewDataBinding是通过View层传递过来。

     private SampleViewModel mSampleViewModel;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ActivitySampleMvvmBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_sample_mvvm);
            mSampleViewModel=new SampleViewModel(binding);
            setDataToView();
        }
        private void setDataToView()
        {
            mSampleViewModel.getUserInfo("uid", new Callback1<SampleModel.UserInfo>() {
                @Override
                public void onCallBack(SampleModel.UserInfo userInfo) {
                    mSampleViewModel.mViewDataBinding.setUser(userInfo);
                }
            });
        }
    

    xml layout代码在上面介绍databing的用法时已给出,通过上面代码我们就将数据UserInfo跟View进行绑定了。比如我们更新用户信息,可以直接对View上的属性进行修改:
    mSampleViewModel.mViewDataBinding.tvName.setText(“rose”);
    也可以通过修改UserInfo实体类的字段信息:
    mSampleViewModel.mViewDataBinding.setUser(userInfo);

    从此告别MVP中View层好多接口的问题,让View变得更简洁,修改任何一方,两者都会保持数据同步。

    5、MVVM 总结

    看起来MVVM很好的解决了MVC和MVP的不足,但是由于数据和视图的双向绑定,导致出现问题时不太好定位来源,有可能数据问题导致,也有可能业务逻辑中对视图属性的修改导致。如果项目中打算用MVVM的话可以考虑使用官方的架构组件ViewModel、LiveData、DataBinding去实现MVVM

    关于MVC,MVP,MVVM如何选择的探讨

    前面在介绍MVC、MVP、MVVM时并没有去详细列出他们的优缺点,主要原因有两个:

    1. 网上这方面总结的还是挺多的
    2. 其实关于架构,设计,模块化等等,它们的优缺点没有绝对的,主要看实现者如何去做

    比如在mvp中我们要实现根据业务逻辑和页面逻辑做很多Present和View的具体实现,如果这些case太多,会导致代码的可读性变差。但是通过引入contract契约类,会让业务逻辑变得清晰许多。因此不管是用哪种设计模式,只要运用得当,都可以达到想要的结果。

    如果非要说怎么选的话,以我浅薄的知识建议如下:

    1. 如果项目简单,没什么复杂性,未来改动也不大的话,那就不要用设计模式或者架构方法,只需要将每个模块封装好,方便调用即可,不要为了使用设计模式或架构方法而使用。
    2. 对于偏向展示型的app,绝大多数业务逻辑都在后端,app主要功能就是展示数据,交互等,建议使用mvvm。
    3. 对于工具类或者需要写很多业务逻辑app,使用mvp或者mvvm都可。
    4. 如果想通过一个项目去学习架构和设计模式,建议用MVC然后在此基础上慢慢挖掘改进。最后你可能发现,改进的最终结果可能就变成了mvp,mvvm。

    PS:代码部分很多只是为了演示具体设计模式原理,部分为伪代码,还有些代码写的不是那么严谨。本篇文章参考如下:

    http://www.voidcn.com/article/p-ssodjasa-brk.html
    https://www.jianshu.com/p/4830912f5162

    欢迎关注我的微信公众号,接收第一手技术干货

    展开全文
  • MVPMVP“最有希望获得最佳MVP”之“最有希望获得最佳MVP”之“最有希望获得最佳MVP”之“最有希望获得最佳MVP”之“最佳MVP”之“最佳MVP”之“最佳MVP”之“最佳MVP”之“最佳MVP”之“最佳MVP”之“最佳MVP”...
  • MVPMVP契约者与MVP契约者的封装 MVP架构是为了让各个模块之间降低耦合,方便维护,也可以让代码更简洁,让代码简洁的意思是让代码更清晰,并不是让代码更少;MVP契约者是为了进一步的低耦合、接口统一管理。 本文...
  • MVP模型

    2020-02-17 15:55:55
    1、MVP模型简介 MVP即Model-View-Presenter模型 说明:1)MVPActivity需要实现IMVPView接口,含有MVPPresenter的引用 2)MVPModel是数据的处理 3)MVPPresenter是连接View和Model的,含有View和Modle的引用 2...
  • MVP模式之初识MVP

    2018-03-16 11:52:22
    犹豫了很久,还是决定静下心来写一写自己实践的MVP模式相关的内容,我怕我再不写,就要丢失了那些采坑的记忆,就要丢失了写博客的习惯,最可怕的是,再不写,可能就帮不了那些真正想要了解和使用MVP的童鞋们了。...
  • android MVP

    2019-07-16 15:39:16
    文章 Android MVP模式 简单易懂的介绍方式 讲的很透彻,从这篇入手足矣。 (github:https://github.com/kaedea/Android-MVP-Pattern) 然后学习Google给出的的 todo-mvp 示例 推荐阅读 从google todo-mvp示例再次...
  • MVP模式

    2019-09-05 09:16:41
    MVP模式MVPMVC与MVP区别:优势: MVP 全称:Model-View-Presenter。 Model:提供数据 View:显示 Controller/Presenter负责逻辑处理 MVC与MVP区别: MVP中,VIew不直接使用Model,它们之间的通信是通过Presenter...
  • Building MVP apps: MVP Part I http://www.gwtproject.org/articles/mvp-architecture.html
  • mvp演示例子

    2017-07-08 18:21:05
    MVP+Retrofit+Rxjava
  • Android MVP项目的搭建Demo(MVP+Dagger2+Butterknife)
  • AndroidMVP

    万次阅读 2016-06-22 09:17:58
    Mvp模式简介衍生于MVC 模式,降低了耦合性,避免了View(Activity/Fragment)承担了所有的责任, 分担了UI层的职责。在MVP模式里通常包含4个要素: * View:负责绘制UI元素、与用户进行交互(在Android中体现为...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 28,008
精华内容 11,203
关键字:

mvp