
- 外文名
- National Basketball Association Most Valuable Player Award
- 奖杯名称
- 莫里斯·波多罗夫杯
- 出 处
- NBA
- 中文名
- 美国职业篮球联赛最有价值球员奖
- 开始时间
- 1955-56赛季
-
MVP
2019-03-18 08:01:30OKHttp 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:51presenters/** * Created by lyl on 2016/3/17. ...public abstract class MVPBasePresenter<V extends MVPView> implements MVPPresenter<V> { private WeakReference<V> viewRef; public void attachViewpresenters
/** * 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,先简单了解下,文中会有例子到时候可以直观的感受下。
小总结下,也就是说,之所以让人觉得耳目一新,是因为这次的跳跃是从
并不标准的MVC
到MVP
的一个转变,减少了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
(欢迎关注,第一时间推送博文信息)
参考资料
- https://github.com/zhengxiaopeng/Rocko-Android-Demos/tree/master/android-mvp
- https://github.com/antoniolg/androidmvp
- https://github.com/pedrovgs/EffectiveAndroidUI
- http://zhengxiaopeng.com/2015/02/06/Android%E4%B8%AD%E7%9A%84MVP/
- http://magenic.com/Blog/Post/6/An-MVP-Pattern-for-Android
- http://antonioleiva.com/mvp-android/
- http://konmik.github.io/introduction-to-model-view-presenter-on-android.html
-
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相关资料时,如果你多看几篇文章的话可能会发现,好像他们介绍的设计图都不太一样,这里罗列了大部分的设计图
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的设计图:
一般情况下就这两种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设计图:
一般情况下就这两种情况,这看起来跟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时并没有去详细列出他们的优缺点,主要原因有两个:
- 网上这方面总结的还是挺多的
- 其实关于架构,设计,模块化等等,它们的优缺点没有绝对的,主要看实现者如何去做
比如在mvp中我们要实现根据业务逻辑和页面逻辑做很多Present和View的具体实现,如果这些case太多,会导致代码的可读性变差。但是通过引入contract契约类,会让业务逻辑变得清晰许多。因此不管是用哪种设计模式,只要运用得当,都可以达到想要的结果。
如果非要说怎么选的话,以我浅薄的知识建议如下:
- 如果项目简单,没什么复杂性,未来改动也不大的话,那就不要用设计模式或者架构方法,只需要将每个模块封装好,方便调用即可,不要为了使用设计模式或架构方法而使用。
- 对于偏向展示型的app,绝大多数业务逻辑都在后端,app主要功能就是展示数据,交互等,建议使用mvvm。
- 对于工具类或者需要写很多业务逻辑app,使用mvp或者mvvm都可。
- 如果想通过一个项目去学习架构和设计模式,建议用MVC然后在此基础上慢慢挖掘改进。最后你可能发现,改进的最终结果可能就变成了mvp,mvvm。
PS:代码部分很多只是为了演示具体设计模式原理,部分为伪代码,还有些代码写的不是那么严谨。本篇文章参考如下:
http://www.voidcn.com/article/p-ssodjasa-brk.html
https://www.jianshu.com/p/4830912f5162
欢迎关注我的微信公众号,接收第一手技术干货 -
Beam,“MVP”MVP“最有希望获得最佳MVP”之“最有希望获得最佳MVP”之“最有希望获得最佳MVP”之“最有希望...
2019-10-13 08:01:14“MVP”MVP“最有希望获得最佳MVP”之“最有希望获得最佳MVP”之“最有希望获得最佳MVP”之“最有希望获得最佳MVP”之“最佳MVP”之“最佳MVP”之“最佳MVP”之“最佳MVP”之“最佳MVP”之“最佳MVP”之“最佳MVP”... -
MVP与MVP契约者与MVP契约者的封装
2019-10-27 23:13:47MVP与MVP契约者与MVP契约者的封装 MVP架构是为了让各个模块之间降低耦合,方便维护,也可以让代码更简洁,让代码简洁的意思是让代码更清晰,并不是让代码更少;MVP契约者是为了进一步的低耦合、接口统一管理。 本文... -
MVP模型
2020-02-17 15:55:551、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:41MVP模式MVPMVC与MVP区别:优势: MVP 全称:Model-View-Presenter。 Model:提供数据 View:显示 Controller/Presenter负责逻辑处理 MVC与MVP区别: MVP中,VIew不直接使用Model,它们之间的通信是通过Presenter... -
Building MVP apps: MVP Part I
2020-09-08 16:36:51Building MVP apps: MVP Part I http://www.gwtproject.org/articles/mvp-architecture.html -
mvp演示例子
2017-07-08 18:21:05MVP+Retrofit+Rxjava -
Android MVP项目搭建(MVP+Dagger2+Butterknife)
2018-11-27 16:55:20Android MVP项目的搭建Demo(MVP+Dagger2+Butterknife) -
AndroidMVP
2016-06-22 09:17:58Mvp模式简介衍生于MVC 模式,降低了耦合性,避免了View(Activity/Fragment)承担了所有的责任, 分担了UI层的职责。在MVP模式里通常包含4个要素: * View:负责绘制UI元素、与用户进行交互(在Android中体现为...
-
虚拟路由器冗余协议【原理篇】VRRP详解
-
MySQL 数据库权限管理(用户高级管理和精确访问控制)
-
html-css-DAY03
-
Galera 高可用 MySQL 集群(PXC v5.7+Hapro)
-
LVS + Keepalived 实现 MySQL 负载均衡与高可用
-
256变4096:麒麟网2注册分库分表扩容如何实现平滑数据迁移?
-
mysql提示表不存在的解决方法error: 1146: Table doesn‘t exist
-
基于java springboot银行卡业务系统的设计与实现(B/S模式含数据库和源码)
-
‘Cannot read property ‘changeSelect‘ of null’报错?
-
C语言零基础入门(详细讲解)
-
2018年TI杯大学生电子设计竞赛本科组D组手势识别装置源程序
-
Oracle regexp_substr
-
VUE项目中如何使用SCSS
-
阿里云ECS服务器的共享型ip会和别人共享吗?
-
MySQL 索引
-
华为1+X——网络系统建设与运维(高级)
-
Docker从入门到精通
-
AI拍照识花.rar
-
js中计算指定日期范围内的所有日期
-
艾媒咨询:电子合同市场规模超100亿,君子签加速企业数字化转型