学习区android开发专题RxJava

像小白一样学习MVP

2016-08-16  本文已影响1588人  Souv

MVP与MVC

MVP是从MVC的延伸。为什么要会出现MVP模式:那我们得了解一下MVC模式到底是一个怎样的模式:
我们先看MVC模式:view层和model是直接沟通的,model是逻辑、业务、数据层。model这里面涉及到的东西特别多,包括:数据库存储、网络数据获取、文件数据读取等;虽然MVC中也是主要将UI和业务逻辑及数据进行分离,而我们在使用MVC模式的时候也是将这些数据逻辑等封装在单独的类进行操作,但是这里面的还是太多。导致我们的activity成为了”万能的activity“。
而这个时候我们看下MVP模式:

MVP和MVC对比图

1:view和model层是分离的,他是通过presenter进行沟通。所以UI和逻辑、数据的交互都在presenter中。
2:因为view脱离了model层,所以activity将只要通过接口与presenter进行沟通,从而减少了大量的逻辑、数据代码。


MVP的优点

1、模型与视图完全分离,我们可以修改视图而不影响模型;
2、可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部;
3、我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁;
4、如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)。


MVP实操

MVP中我觉得先写M 然后写V 再写P。因为P是桥梁。
我们看下项目包架构

mvp项目包架构

我是根据每个功能来建立包名的,wificonfig是我写的一个wifi配置功能,这里面的所有流程按照mvp框架来写。所以里面分别建立了model、presenter、view包。我没有将bean类放到这里面来是因为单独拿出来可能会好找点,其实这个也没那么重要。

mvp中的M

先说Model:数据逻辑层;主要处理数据的存取、逻辑的处理等。
model主要分为一个接口,一个类:这样会简洁。
首先看接口:
<pre>
<code>
public interface WIFIModel {

/* 获取wifi列表  */    

void getWifiListInfo();    

/* 从网络读取wifi列表  */    

List<WifiInfoBean> loadWifiListInfo();    

  /*  判断wifi是否打开  */    

boolean getWifiStatus();    

/*  设置wifi状态   */    

boolean setWifiStatus(boolean isConn);

}
</code>
</pre>
主要提供你需要做的功能接口。我这里是设置wifi、获取wifi列表。然后新建一个类实现此接口中的所有方法
<pre>
<code>
public class WIFIModelImp implements WIFIModel {

private static final String TAG = WIFIModelImp.class.getSimpleName();

private Context context = null;

/** 对象实例类及list实例 **/

private List wifiInfoBeanList = new ArrayList();

private List list = null;

private ScanResult mScanResult = null; //ScanResult类描述了一个已发现AP的信息。

private WifiAdmin wifiAdmin = null;

public WIFIModelImp(Context ctx){

context = ctx;

wifiAdmin = new WifiAdmin(context);

}

@Override

public void getWifiListInfo() {

}

@Override

public List loadWifiListInfo() {

list = wifiAdmin.getWifiList();

if(null != list && list.size() > 0){

for(int i=0; i<list.size(); i++){

    mScanResult = list.get(i);

    WifiInfoBean wifiInfoBean = new 
    WifiInfoBean(mScanResult.SSID,mScanResult.capabilities,mScanResult.level);
    wifiInfoBeanList.add(wifiInfoBean);

}

}

return wifiInfoBeanList;

}

@Override

public boolean getWifiStatus() {

  boolean isConn = wifiAdmin.isConn(context);

  return isConn;

}

@Override

public boolean setWifiStatus() {

  boolean isConn = wifiAdmin.isConn(context);

  if(isConn){

    //进行wifi关闭操作

      wifiAdmin.closeWifi();

      isConn = false;

    } else {

    //进行wifi打开操作

    wifiAdmin.openWifi();

    isConn = true;

    }

    return isConn;

}

}
</code>
</pre>
实现接口中的所有方法,然后再不同的方法,实现不同的功能逻辑处理。

mvp中的V

然后我们看V:主要做界面显示。你会发现在这里所有的显示都在这里用方法来实现。哪怕是一个text.settext()、img.setbackage();
<pre>
<code>
public interface WIFIView {

WifiInfoBean getWIFIInfo();

/** 显示wifi开关状态 **/

void showWifiConnStatus(boolean isConn);

/** list显示 **/

void showRecyList(List list);

}
</code>
</pre>
其中activity也是属于V中的一部分。

mvp中的P

然后我们看P:主要做为V视图层和M逻辑层的桥梁。所有UI与数据的交互都通过P来进行,而同样,都通过接口来实现
<pre>
<code>
public class WIFIPresenter {

private static final String TAG = WIFIPresenter.class.getSimpleName();

private Context ctx = null;

/* 实体类对象和list对象定义 */

private List wifiInfoBeanList = null;

/* 类对象的定义 */

private WIFIModel wifiModel = null;

private WIFIView wifiView = null;

private WIFIInfoAdapter wifiInfoAdapter = null;

public WIFIPresenter(Context context, WIFIView view){

ctx = context;

wifiView = view;

wifiModel = new WIFIModelImp(context);

}

/**
*@descriptoin 获取wifi列表

*@author dc

*@param

*@date 2016/8/12 11:07

*@return wifi list

*/

public void loadWifiList(){

wifiInfoBeanList = wifiModel.loadWifiListInfo();

Log.e(TAG,"wifiList is size=" + wifiInfoBeanList.size());

if (null != wifiInfoBeanList && wifiInfoBeanList.size() > 0) {

      wifiView.showRecyList(wifiInfoBeanList);

}

}

/**
*@descriptoin 获取wifi是否打开状态

*@author dc

*@param

*@date 2016/8/12 11:09

*@return false:关闭 true:打开

*/

public boolean getIsWifiConn(){

return wifiModel.getWifiStatus();

}

/**
*@descriptoin 判断wifi是否打开,并获取wifi列表

*@author dc

*@param

*@date 2016/8/12 14:08

*@return

*/

public void getWifiList(){

/* 获取wifi状态:是否打开 */

boolean isWifiSwift = getIsWifiConn();

wifiView.showWifiConnStatus(isWifiSwift);

if(isWifiSwift) {

      //获取wifi列表

      loadWifiList();

}

}

/**
*@descriptoin 设置wifi状态

*@author dc

*@param

*@date 2016/8/12 14:16

*@return

*/

public void setWifiStatus(){

/* 设置wifi状态 */

boolean isWifiSwift = wifiModel.setWifiStatus();

wifiView.showWifiConnStatus(isWifiSwift);

}

/**
*@descriptoin 清空list

*@author dc

*@param

*@date 2016/8/12 14:59

*@return

*/

public void clearWifiList(){

if(null != wifiInfoBeanList){

      wifiInfoBeanList.clear();

      wifiView.showRecyList(wifiInfoBeanList);

}

}
</code>
</pre>
我们可以看到P中的所有方法,都是通过V或M的接口来操作M或V。
比如:
<pre>
<code>
public void loadWifiList(){

wifiInfoBeanList = wifiModel.loadWifiListInfo();

Log.e(TAG,"wifiList is size=" + wifiInfoBeanList.size());

if (null != wifiInfoBeanList && wifiInfoBeanList.size() > 0) {

      wifiView.showRecyList(wifiInfoBeanList);

}

}
</code>
</pre>
获取wifi列表属于数据的读取,我们在M中属性此方法。
<pre>
<code>
wifiInfoBeanList = wifiModel.loadWifiListInfo();
</code>
</pre>
然后获取数据list之后,需要展示在UI上,我们知道UI的显示在V中实现
<pre>
<code>
wifiView.showRecyList(wifiInfoBeanList);
</code>
</pre>
这样我们很容易的看到P 主要就是连接M和V。在M和V的交互中通过接口来起到桥梁的作用。
主要查看一下P的构造方法。
<pre>
<code>
public WIFIPresenter(Context context, WIFIView view){

ctx = context;

wifiView = view;

wifiModel = new WIFIModelImp(context);

}
</code>
</pre>
因为M有实现类,所以直接new 他的构造方法进行初始化。

mvp中的Activity或Fragment

而V主要是UI的展示。他主要是在activity或fragment中进行展示,所以我们在activity中需要impments V的接口
<pre>
<code>

public class WIFIConfigActivity extends AppCompatActivity implements WIFIView ,View.OnClickListener{

@Override

public WifiInfoBean getWIFIInfo() {

    return null;

}

@Override

public void showWifiConnStatus(boolean isConn) {

  Log.e(TAG, "wifi是否打开:" + isConn);

  if(!isConn){
   //wifi 已关闭
    activityWificonfigSwitchImg.setBackgroundResource(R.drawable.switch_off);

} else {

    //wifi 已打开
    activityWificonfigSwitchImg.setBackgroundResource(R.drawable.switch_on);

}

}

@Override

public void showRecyList(List list) {

wifiInfoAdapter = new WIFIInfoAdapter(WIFIConfigActivity.this, list);

activityWificonfigListRv.setAdapter(wifiInfoAdapter);
}

}
</code>
</pre>
其中activity实现了view,并实现了他的所有方法。然后再对应的方法中实现UI展示

<pre>
<code>
@Override

public void showRecyList(List list) {

wifiInfoAdapter = new WIFIInfoAdapter(WIFIConfigActivity.this, list);

activityWificonfigListRv.setAdapter(wifiInfoAdapter);

}
</code>
</pre>
得到list之后再此方法中显示Adapter的适配。
<pre>
<code>
private WIFIPresenter wifiPresenter = null;

wifiPresenter = new WIFIPresenter(WIFIConfigActivity.this, WIFIConfigActivity.this);
</code>
</pre>
其中需要创建一个P来作为桥梁来交互M和V。
如:
<pre>
<code>
//获取wifi列表

wifiPresenter.getWifiList();
</code>
</pre>


总结:
MVP:个人觉得他的优点还是蛮多的。
1:他让我的act很简洁,act不再是“万能的”。
2:然后数据和界面的交互是独立的,修改界面不影响数据,修改数据不影响界面。对于单元测试特方便。
3:所有的交互都在P中,方便我们查找问题


M:主要做数据和逻辑处理。最好通口和实现类的方式实现。在M中,我们可以处理数据的存储,读取、获取数据获取、提交、数据库操作等。达到了数据与视图的分离,数据的集中管控的效果。
V:主要做界面的显示:哪怕是一个textview的显示,listview的显示等所有与界面相关的都可以在V中通过接口来实现。开始我以为V的作用并不大,因为我们在act中显示界面其实也没什么复杂的,代码也不会很多。但是只要结合MVP模式来看的话,还是很震惊的。个人理解他主要是让act不存在任何的逻辑处理,什么时候显示界面,什么时候不显示都不用act来控制。都用P来统一规范。
P:主要处理M与V的交互。P作为桥梁很好理解他就是通过获取M数据来控制V的显示,或者通过获取V数据来保存到M中做数据逻辑处理。所以P的作用还是蛮大的。程序只要出了问题,直接中P中对应的方法找,然后查看P是调用的那个M或V,对查找问题我也觉得是很方便的。


小白初步学习MVP,以上也只是个人的MVP的了解,肯定有不对之处,还请多多指教。
PS:markdown代码换行好麻烦啊,有简单一点的操作吗

上一篇下一篇

猜你喜欢

热点阅读