日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

MVP 與 MVC 簡介

MVP 軟件架構(gòu)在現(xiàn)在的應(yīng)用中, 特別是 Android 端的編程中尤為突出的使用,因為 MVP 架構(gòu)可以很深層次的去解耦視圖、業(yè)務(wù)邏輯、數(shù)據(jù)源三者的關(guān)系,讓它們之間的相互依賴性降低。MVP 是針對 Android 端開發(fā)而言的,它其實是 MVC 演變過來的,因為 MVC 模式在 Android 開發(fā)中并不是那么愉快。主要表現(xiàn)方面,比如,我們在寫一個功能模塊時,Activity 中的代碼很容易就突破到上千甚至上萬行,除了必要的 findviewid,listener 等,其他的代碼幾乎都是業(yè)務(wù)邏輯相關(guān)的,這就顯得 Activity 非常的臃腫,也不是說不可以,但是在模塊升級時造成業(yè)務(wù)邏輯的改變,我們就需要去成千上萬行的 Activity 中尋找業(yè)務(wù)邏輯代碼,這就有可能出現(xiàn)多處代碼需要修改,不細心的話,非常容易出 Bug,而且除了 Bug 代碼也不好定位。

第二個問題,數(shù)據(jù)源(來自數(shù)據(jù)庫或這網(wǎng)絡(luò))部分可能會寫好幾份,比如,有兩個 Activity 同時有著個人信息數(shù)據(jù)要顯示,我必須在這兩個 Activity 中各請求一次網(wǎng)絡(luò)或者訪問數(shù)據(jù)庫,得到最新的數(shù)據(jù),這就出現(xiàn)了代碼重復(fù)的問題。

帶著這兩個問題,我們來看看 MVP 架構(gòu)能夠怎樣幫助我們解決 MVC 出現(xiàn)的這種問題!首先,我來簡單的介紹一下 MVC 它指的是:

  • model(模型),負責訪問網(wǎng)絡(luò)數(shù)據(jù)、訪問數(shù)據(jù)庫數(shù)據(jù),提供數(shù)據(jù)源
  • view(視圖),負責更新界面、響應(yīng)用戶界面操作
  • controller(控制器),負責業(yè)務(wù)邏輯控制,處理數(shù)據(jù)

我們在 Android 開發(fā)中,Activity 負責 UI 顯示及更新操作,相當于 View 層,我們一般都會把代碼直接寫在 Activity 中,不管是數(shù)據(jù)源、邏輯控制、數(shù)據(jù)處理等操作一個勁的往 Activity 里寫,那么它們?nèi)叩年P(guān)系都互相依賴,你中有我,我中有你,它們就形成了三角的關(guān)系。

Android MVP 架構(gòu)介紹與使用入門

 

這樣的關(guān)系,導(dǎo)致 Activity 代碼量過于龐大,修改和維護起來比較困難。這樣的三角戀關(guān)系,顯然不是長久之際。于是,MVP 它就強行把 View 與 Model 隔離了,讓它們不再有聯(lián)系,傳說中的 Presenter 就是腳踏兩只船,來回奔走于 View 與 Model 之間的契約者、聯(lián)系者。

Android MVP 架構(gòu)介紹與使用入門

 

MVP(model、view 、presenter),將 Activity 中的代碼抽離了出來,把 Activity(Fragment、View) 只當作 View 層,通過一個 Presenter(契約層)將 View 和 Model 層聯(lián)系起來,讓 View 和 Model 層充分的解耦。

我們訪問網(wǎng)絡(luò)得到數(shù)據(jù)并顯示出來會是這樣一個流程:

  1. Activity 啟動時,告訴 Presenter 我要數(shù)據(jù)了
  2. Presenter 就會叫 Model 去訪問數(shù)據(jù)接口得到數(shù)據(jù)
  3. Model 得到原數(shù)據(jù)就交給 Presenter 了,Presenter 一看數(shù)據(jù)不規(guī)范,趕緊處理一下,處理完成
  4. Presenter 就把處理后的數(shù)據(jù)匯報給 Activity(View),View 拿到數(shù)據(jù)就做顯示的操作,工作結(jié)束

MVC

下面我們通過一個簡單的案例來進行了解 MVP 架構(gòu)的代碼寫法,當然,這里的寫法不唯一,因為每個人寫代碼的方式都是不一樣的,最核心的是 MVP 架構(gòu)的思想,把思想轉(zhuǎn)為實際代碼,這才是值得我們探索和學(xué)習(xí)的地方。

來看看代碼,我們在網(wǎng)絡(luò)請求時,獲取到數(shù)據(jù),并 toast 和顯示到 textview 上,這樣的代碼我相信誰都會寫,但一般人都是直接一口氣寫在 MainActivity 類上面,比如這樣:

public class MainActivity extends AppCompatActivity {
 
 private TextView tv;
 private static final String TAG = "MainActivity";
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 
 initViews();
 
 request();
 showDialog();
 }
 
 private void initViews() {
 tv = findViewById(R.id.tv);
 }
 
 private void showDialog() {
 ProgressDialog dialog = new ProgressDialog(this);
 dialog.show();
 new Handler().postDelayed(new Runnable() {
 @Override
 public void run() {
 dialog.dismiss();
 }
 }, 1500);
 }
 
 private void request() {
 OkHttpClient client = new OkHttpClient();
 Request request = new Request.Builder()
 .url("https://www.baidu.com/")
 .build();
 client.newCall(request).enqueue(new Callback() {
 @Override
 public void onFailure(Call call, IOException e) {
 }
 
 @Override
 public void onResponse(Call call, Response response) throws IOException {
 String resp = response.body().string();
 toast(resp);
 }
 });
 }
 
 private void toast(String resp) {
 runOnUiThread(new Runnable() {
 @Override
 public void run() {
 Toast.makeText(MainActivity.this, "" + resp, Toast.LENGTH_SHORT).show();
 tv.setText(resp);
 }
 });
 }
 
}

它的效果其實就是請求百度首頁,返回網(wǎng)頁數(shù)據(jù)以 string 方式顯示出來而已。

Android MVP 架構(gòu)介紹與使用入門

 

上面的代碼,其實就是 MVC 架構(gòu)的寫法,把 Model(網(wǎng)頁數(shù)據(jù))、Presenter(數(shù)據(jù)處理)、View(activity)三層寫在了一起,雖然沒什么問題,但我們看看 MainActivity 中的代碼比較雜亂,在業(yè)務(wù)代碼比較多的情況下,MainActivity 更加的沉重,不利于維護與業(yè)務(wù)升級。

MVP 實戰(zhàn)

那么我們下面就要將這個類中的代碼改寫為 MVP 的寫法,回顧上面提及的 MVP 架構(gòu)的思想,它是將 View 層與 Model 層徹底隔離,意味著 View 和 Model 都不再持對方的引用,它們通過一個第三者 Presenter 來代理事物的傳遞,所以 Presenter 層會持有 Model 與 View 層的引用,這是第一步。

第二步,是將它們之間的聯(lián)系抽象出來,以接口的方式相互調(diào)用,所以 Model 、View、Presenter 各自擁有自己的接口和抽象方法,所以這就會無形的多出了三個接口類,這也就是 MVP 的缺點之一。所以,為了較少的創(chuàng)建接口類,我們就給這三層接口定義了一個契約接口,把它們更加緊密的結(jié)合在一起,方法查看,例如代碼這樣寫:

(1)契約類:

package com.test.mvp.mvpdemo.mvp.v1;
 
import okhttp3.Callback;
 
/**
 * 契約接口,可以很直觀的看到 M、V、P 層接口中提供的方法
 */
public interface MainContract {
 interface IMainModel {
 void requestBaidu(Callback callback);
 }
 
 interface IMainView {
 void showDialog();
 
 void succes(String content);
 }
 
 interface IMainPresenter {
 void handlerData();
 }
}

然后,再將之前的一個單獨的 MainActivity 分包,分別創(chuàng)建 Model 層實現(xiàn)類、Presenter 層實現(xiàn)類、MainActivity 就相當于View 層,這樣一來架構(gòu)就更加清晰明了:

Android MVP 架構(gòu)介紹與使用入門

 

接著,分別給這三層實現(xiàn)我們剛剛寫的 MainContract 中相對應(yīng)的接口,我們先來看看 Model 層,它就主要負責網(wǎng)絡(luò)請求,也就是我們的 OKHttp 請求到百度首頁的一個操作,很簡單的代碼。

(2)Model 層:

package com.test.mvp.mvpdemo.mvp.v1.model;
 
import com.test.mvp.mvpdemo.mvp.v1.MainContract;
 
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
 
/**
 * model 層,請求網(wǎng)絡(luò)或數(shù)據(jù)庫,提供數(shù)據(jù)源(原始數(shù)據(jù))
 */
public class DataModel implements MainContract.IMainModel {
 
 @Override
 public void requestBaidu(Callback callback) {
 OkHttpClient client = new OkHttpClient();
 Request request = new Request.Builder()
 .url("https://www.baidu.com/")
 .build();
 client.newCall(request).enqueue(callback);
 }
}

這里需要傳入一個 OKHttp 的 Callback ,由于不能在 Model 層中處理業(yè)務(wù)數(shù)據(jù),所以我們讓它自己回調(diào)給 Presenter 層來處理,保證數(shù)據(jù)的原始狀態(tài)。

(3)Presenter 層:

然后是 Presenter 層,它是處理業(yè)務(wù)邏輯和業(yè)務(wù)數(shù)據(jù)的,所以必須持有 Model 的引用,同時要將處理完的數(shù)據(jù)交給 View 層用于顯示,也必須持有 View 的引用,那么,一開始我們就要把這兩層給實例化,具體看下面的代碼:

package com.test.mvp.mvpdemo.mvp.v1.presenter;
 
import com.test.mvp.mvpdemo.mvp.v1.MainContract;
import com.test.mvp.mvpdemo.mvp.v1.model.DataModel;
 
import JAVA.io.IOException;
 
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
 
/**
 * presenter 層,承擔業(yè)務(wù)邏輯處理,數(shù)據(jù)源處理等
 */
public class MainPresenter implements MainContract.IMainPresenter {
 
 private MainContract.IMainModel mModel;
 private MainContract.IMainView mView;
 
 public MainPresenter(MainContract.IMainView view) {
 this.mView = view;
 mModel = new DataModel();
 }
 
 @Override
 public void handlerData() {
 if (mView != null) {
 mView.showDialog();
 }
 /**
 * 發(fā)起請求,獲得回調(diào)數(shù)據(jù)
 */
 mModel.requestBaidu(new Callback() {
 @Override
 public void onFailure(Call call, IOException e) {
 }
 
 @Override
 public void onResponse(Call call, Response response) throws IOException {
 String content = response.body().string();
 if (mView != null) {
 mView.succes(content);
 }
 }
 });
 }
}

這里的處理數(shù)據(jù)我就不做說明了,注意一點,這里是請求網(wǎng)絡(luò)數(shù)據(jù)會有延時,我們 Presenter 層持有了 View 層的引用,也就是 Activity 的引用,在網(wǎng)絡(luò)堵塞的情況下,用戶在打開 Activity 又馬上給關(guān)閉了,這時 View 相當于被摧毀了,如果不進行判斷 View 引用是否為空,當數(shù)據(jù)在延遲幾秒后返回時,就會造成空指針異常,所以每次都要進行判斷才合理。

最后,在 Presenter 層處理完了數(shù)據(jù),就要將數(shù)據(jù)傳達給 View 層顯示,所以要調(diào)用 View 接口的抽象方法,把數(shù)據(jù)參數(shù)傳遞過去,那么 View 在收到數(shù)據(jù)后,不需要多余的邏輯操作,直接顯示就好了。那么 View(MainActivity)的代碼應(yīng)該做如下修改:

(4)View 層:

package com.test.mvp.mvpdemo.mvp.v1.view;
 
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Toast;
 
import com.test.mvp.mvpdemo.R;
import com.test.mvp.mvpdemo.mvp.v1.MainContract;
import com.test.mvp.mvpdemo.mvp.v1.presenter.MainPresenter;
 
/**
 * MVP 的寫法,Version 1: 基礎(chǔ)寫法
 */
public class MainActivity extends AppCompatActivity implements MainContract.IMainView {
 
 private TextView tv;
 
 private MainPresenter mPresenter;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 
 initViews();
 
 mPresenter = new MainPresenter(this);
 mPresenter.handlerData();
 }
 
 private void initViews() {
 tv = findViewById(R.id.tv);
 }
 
 @Override
 public void showDialog() {
 ProgressDialog dialog = new ProgressDialog(this);
 dialog.show();
 new Handler().postDelayed(new Runnable() {
 @Override
 public void run() {
 dialog.dismiss();
 }
 }, 1500);
 }
 
 @Override
 public void succes(String content) {
 runOnUiThread(new Runnable() {
 @Override
 public void run() {
 Toast.makeText(MainActivity.this, "" + content, Toast.LENGTH_SHORT).show();
 tv.setText(content);
 }
 });
 }
}

使用 MVP 架構(gòu),我們可以做到 Model 層和 Presenter 層的復(fù)用,如果不同的 Veiw 層需要相同的數(shù)據(jù),那么就無需修改 Model 層和 Presenter 層,直接實現(xiàn)接口就可以了。

到此為止,一個從網(wǎng)絡(luò)獲取數(shù)據(jù)并顯示的案例就被我們改寫為 MVP 架構(gòu)了,這是最基礎(chǔ)的 MVP 的入門版本,其中精要的就是interface 接口的使用,而接口的用法也是 Java 的基礎(chǔ),所以本篇文章內(nèi)容應(yīng)該不難理解。而 MVP 架構(gòu)也無需引入哪些庫、框架啊等等,它更是一種編程架構(gòu)、編程思想,并且現(xiàn)在也非常流行,所以我們一定要搞定它。

最后

如果你看到了這里,覺得文章寫得不錯就給個贊唄!歡迎大家評論討論!如果你覺得那里值得改進的,請給我留言。一定會認真查詢,修正不足,定期免費分享技術(shù)干貨。謝謝!

分享到:
標簽:架構(gòu) Android MVP
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定