mvp架構模式


        今天是國慶節,祝你們節日快樂,願祖國愈加繁榮昌盛。假期程序員也不能偷懶,更新一些博文吧。前端

        看到封面圖片喜歡NBA的人可能很容易就想到了最有價值球員。可是此mvp非彼MVP,此mvp指的是如今Android開發中比較常見的一種軟件架構模式。mvp架構模式是Google官方推薦的架構模式,特別是近年來的新項目,mvp+retrofit+rxjava+dragger2配合使用已經在引領程序界的潮流了,在github上能夠輕易的搜到一大堆這樣的開源項目。前端時間筆者也在公司的一個sdk上進行了嘗試,在此算是作個簡單的總結吧。本文主要介紹什麼是mvp架構模式,還有這種架構模式的優點以及如何使用它搭建你的項目。java

        1、mvp爲什麼物git

我以前在公司項目中作嘗試的時候,提交代碼後公司同事曾問過我這個問題,程序員

我當時做了個簡單的解釋,這也是我學習過程當中總結出來的,若是要作一個比較正規的定義,我以爲應該這麼說:mvp 是從經典的mvc模式演變過來的,其基本思路都是相通的。其中M是model模型,提供業務數據;P是Presenter控制者,進行邏輯處理。V是View視圖,顯示數據。在MVP中View並不直接使用Model,它們之間的通訊是經過Presenter 來進行的,全部的交互都發生在Presener內部。在筆者的世界裏,mvp架構模式的定義就是這樣的,若是你看到這裏以爲難以接受這個定義,或者你認爲這是錯誤的觀點,就不建議你繼續往下看了,建議直接留言聯繫筆者進行探討。github

        2、mvp架構模式的優點編程

若是你讀到這裏,說明你應該是已經接受筆者對mvp架構模式的定義了。接下來要闡述的是mvp架構模式的優點。衆所周知,Android原生應用開發使用的是Java語言(至少目前絕大多數是),Java語言是面向對象的,面向對象的六大原則其中之一是單一職責原則,它的官方定義是There should never be more than one reason for a class to change,應該有且僅有一個緣由引發類的變動。說到底就是解耦合。對,解耦合,這就是mvp架構模式的終極目標,也是它最大的優點。爲何要把架構裏的各個層次分得清清楚楚,每一個層面負責什麼,不該該負責負責,如何組合起來都須要嚴格的定義起來,你要知道,每一種架構都不是編碼規範,也不是組織代碼的規範,它們都是一種思惟方式。因此在實踐中你永遠要記住你爲何使用mvp架構模式,切忌忘記初衷,爲了炫酷而在使用mvp。json

        3、mvp架構模式的簡單實踐服務器

沒錯,在碼農的世界裏任何語言都是蒼白無力的,仍是代碼來的實際。稍安勿躁,代碼立刻就來。可是仍是要提醒你們,只會寫代碼的不叫程序員,叫代碼搬運工(就是搬磚的),學會編程以後就要昇華一下,去掌握編程思想,以讓你的代碼更優雅,這句話是前幾天老大跟我說的,在此送給你們。網絡

爲演示mvp架構模式的使用,筆者寫了一個簡單的小demo,demo主要功能是去服務器請求App版本更新的信息,服務器會返回版本信息,包括最新版本名,一個提示字段,還有是否須要更新的字段,將返回的數據封裝Version實體類,代碼以下:架構

 

public class Version {
//是否有新版本
   private String hasNewVersion;
   //描述
   private String desc;
   //最新版本名
   private String latest_version;

   public String getHasNewVersion() {
return hasNewVersion;
   }

public String getDesc() {
return desc;
   }

public String getLatest_version() {
return latest_version;
   }

public void setHasNewVersion(String hasNewVersion) {
this.hasNewVersion = hasNewVersion;
   }

public void setDesc(String desc) {
this.desc = desc;
   }

public void setLatest_version(String latest_version) {
this.latest_version = latest_version;
   }
}

主界面有兩個TextView,一個用於顯示版本名,一個用於顯示版本的描述,還有一個按鈕,點擊按鈕會觸發請求,代碼以下:

public class VersionActivity extends AppCompatActivity implements VersionView{
private TextView tv_versionName;
   private TextView tv_desc;
   private VersionPresenter mVersionPresenter;
   @Override
   protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_mvp);
       mVersionPresenter=VersionPresenter.getInstance(this,this);
       tv_desc=(TextView) findViewById(R.id.tv_desc);
       tv_versionName=(TextView) findViewById(R.id.tv_versionname);
       findViewById(R.id.tv_but).setOnClickListener(new View.OnClickListener() {
@Override
           public void onClick(View v) {
mVersionPresenter.getNewVersion("http://10.180.152.101:8080/NetWorkServer/updateappversion"+"?currentversion=1.4");
           }
});
   }

@Override
   public void showVersionNameAndDesc(Version version) {
tv_versionName.setText("最新版本名: "+version.getLatest_version());
       tv_desc.setText(version.getDesc());

   }

@Override
   public void showToast(String msg) {
Toast.makeText(VersionActivity.this, msg, Toast.LENGTH_LONG).show();
   }
}

該Activity實現了VersionView接口,這就是mvp中的view層,用於跟用戶交互,顯示數據。咱們能夠看到VersionPresenter的初始化,VersionPresenter屬於presenter層,用於處理view與model層的通訊,不讓view直接操做model,可見用戶點擊按鈕後,就通知VersionPresenter去獲取版本信息,至於如何獲取版本信息,presenter層會交給對應的model去進行處理,下面是VersionPresenter的代碼:

 

public class VersionPresenter extends IPresenter {
private static VersionPresenter mVersionPresenter;
   private VersionModel mVersionModel;
   private VersionView mVersionView;
   private Context mContext;
   private VersionPresenter(Context context,IView view){
this.mContext=context;
       this.mVersionView=(VersionView) view;
       this.mVersionModel=new VersionModel();
   }

public static VersionPresenter getInstance(Context context, VersionView view){
if (mVersionPresenter==null){
synchronized (VersionPresenter.class){
if (mVersionPresenter==null){
mVersionPresenter=new VersionPresenter(context,view);
               }
}
}
return mVersionPresenter;
   }
//獲取最新版本
   public void getNewVersion(String url){
mVersionModel.getNewVersion(mContext,url, new VersionModel.VersionCallback() {
@Override
           public void onVersionCallback(final  Version version) {
((Activity)mContext).runOnUiThread(new Runnable() {
@Override
                   public void run() {
mVersionView.showVersionNameAndDesc(version);
                       if (version.getHasNewVersion().equals("true")){
mVersionView.showToast("App有新版本,請更新");
                       }
}
});

           }
});
   }

}

用戶通知presenter後,presenter就把view的需求通知model層,數據操做交給model層去作具體實現,能夠見到在VersionPresenter的getNewVersion方法中只是把view傳過來的參數給到model,具體的網絡請求交給VersionModel去實現,下面是VersionModel的具體實現:

public class VersionModel implements IModel {
public interface VersionCallback {
void onVersionCallback(Version version);
   }

private HttpURLConnection httpURLConnection = null;
   private InputStream inputStream = null;
   private BufferedReader bufferedReader = null;

   public void getNewVersion(Context context,final String url, final VersionCallback versionCallback) {

new Thread(new Runnable() {
@Override
           public void run() {
try {
httpURLConnection = (HttpURLConnection) new URL(url).openConnection();
                   httpURLConnection.connect();
                   inputStream = httpURLConnection.getInputStream();
                   bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
                   StringBuilder stringBuilder = new StringBuilder();
                   String tempLine = null;
                   while ((tempLine = bufferedReader.readLine()) != null) {
stringBuilder.append(tempLine).append("\n");
                   }
String data = stringBuilder.toString();
                   Log.e("data", data);
                   JSONObject jsonObject=null;
                   jsonObject = new JSONObject(data);
                   Version version=new Version();
                   version.setLatest_version(jsonObject.optString("latest_version"));
                   version.setDesc(jsonObject.optString("desc"));
                   version.setHasNewVersion(jsonObject.optString("hasNewVersion"));
                   versionCallback.onVersionCallback(version);
               } catch (Exception e) {
e.printStackTrace();
               } finally {
try {
bufferedReader.close();
                       inputStream.close();
                   } catch (Exception e) {

}
}
}
}).start();
   }
}

VersionModel去執行網絡請求,獲取到VersonView須要的數據而後回調到VersionPresenter,再由VersionPresenter通知VersonView去作UI的變化或者其餘一些操做。縱觀整個過程能夠發現,view層和model層沒有一絲耦合,這就是mvp架構模式的初衷,作到了鬆耦合,view,model,presenter每一層負責自身的工做,毫不越界。

總結

        因爲服務器代碼也是本身寫的,只有一個請求接口,數據的交互也很簡單,可是麻雀雖小五臟俱全,服務器端跟客戶端都在儘可能模擬實際開發中的流程,真個mvp架構模式的基本流程都有了,在此也附上源碼地址,源碼中有服務器和客戶端的代碼:https://github.com/shanyezhihe/mvpdemo.git        

                                                                                               掃碼關注本公衆號

相關文章
相關標籤/搜索