1. 程式人生 > >Android MVP 實踐之路(理解篇)

Android MVP 實踐之路(理解篇)

一.簡單介紹下MVP

1.什麼是mvp?
簡稱:MVP 全稱:Model-View-Presenter ;MVP 是從經典的模式MVC演變而來,它們的基本思想有相通的地方:Controller/Presenter負責邏輯的處理,Model提供資料,View負責顯示。
2.mvp 與mvc 的區別?
在MVP中View並不直接使用Model,它們之間的通訊是通過Presenter (MVC中的Controller)來進行的,所有的互動都發生在Presenter內部,而在MVC中View會直接從Model中讀取資料而不是通過 Controller。
3.優點和缺點介紹
優點:
1、模型與檢視完全分離,我們可以修改檢視而不影響模型
2、可以更高效地使用模型,因為所有的互動都發生在一個地方——Presenter內部
3、我們可以將一個Presenter用於多個檢視,而不需要改變Presenter的邏輯。這個特性非常的有用,因為檢視的變化總是比模型的變化頻繁。
4、如果我們把邏輯放在Presenter中,那麼我們就可以脫離使用者介面來測試這些邏輯(單元測試)
缺點:
由於對檢視的渲染放在了Presenter中,所以檢視和Presenter的互動會過於頻繁。還有一點需要明白,如果Presenter過多地渲染了檢視,往往會使得它與特定的檢視的聯絡過於緊密。一旦檢視需要變更,那麼Presenter也需要變更了。比如說,原本用來呈現Html的Presenter現在也需要用於呈現Pdf了,那麼檢視很有可能也需要變更。

二.看下實現的效果圖

三.接下來是程式碼實現的過程

1.從建立開始
第1步:開啟Android Studio 然後新建一個工程;
第2步:在工程中,新建三個包,分個層,分別是modle、view、presenter
第3步:思考下我們要實現的功能,模擬網路請求,然後點選Button,實現頁面上的TextView的文字改變,這中間我們用Handler模擬一下網路請求
第4步:思考一下我們在MVC的時候,Activity要實現的方法:
a.點選按鈕請求資料
b.當資料請求成功後,呼叫此介面顯示資料
c.當資料請求失敗後,呼叫此介面提示
d.當資料請求異常,呼叫此介面提示
e.顯示正在載入進度框
f.隱藏正在載入進度框
第5步:根據上面分析在MVC中所要實現的方法,我們來實現在MVP的View層的介面中需要實現這幾個方法;
public interface MvpView {
/**
 * 顯示正在載入進度框
 */
void showLoading();
/**
 * 隱藏正在載入進度框
 */
void hideLoading();
/**
 * 當資料請求成功後,呼叫此介面顯示資料
 * @param data 資料來源
 */
void showData(String data);
/**
 * 當資料請求失敗後,呼叫此介面提示
 * @param msg 失敗原因
 */
void showFailureMessage(String msg);
/**
 * 當資料請求異常,呼叫此介面提示
 */
void showErrorMessage();

}

第6步:我們的View層好像寫好了,接下來我們來想想我們的model層吧。其實很簡單,我們說了model層是資料獲取傳輸的層,那麼在model中建立個model類,然後寫一個獲取資料的靜態方法,這是獲取到資料了,那麼我們獲取到的資料怎麼傳遞給我們的Presenter呢? 不饒了,利用介面Callback方法來進行資料的回撥;兩段程式碼如下:

MvpModel類

public class MvpModel {
/**
 * 獲取網路介面資料
 *
 *
 * @param param    請求引數
 * @param callback 資料回撥介面
 */
public static void getNetData(final String param, final MvpCallback callback) {
    // 利用postDelayed方法模擬網路請求資料的耗時操作
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            callback.onSuccess("模擬網路請求得到的資料");
            callback.onComplete();
        }
    }, 2000);
}
}

MvpCallback類

public interface MvpCallback {
/**
 * 資料請求成功
 *
 * @param data 請求到的資料
 */
void onSuccess(String data);

/**
 * 使用網路API介面請求方式時,雖然已經請求成功但是由
 * 於{@code msg}的原因無法正常返回資料。
 */
void onFailure(String msg);

/**
 * 請求資料失敗,指在請求網路API介面請求方式時,出現無法聯網、
 * 缺少許可權,記憶體洩露等原因導致無法連線到請求資料來源。
 */
void onError();

/**
 * 當請求資料結束時,無論請求結果是成功,失敗或是丟擲異常都會執行此方法給使用者做處理,通常做網路
 * 請求時可以在此處隱藏“正在載入”的等待控制元件
 */
void onComplete();

}
第7步:如上方法實現後,那我們的View和model層都有了,我們要實現presenter層,這個是作為中間轉換成,要實現model層和view層的方法;所以要傳遞一個實現View介面的視窗檢視進來,然後呼叫model層的資料獲取方法,將model層的資料展示給我我們的view哦;啥都不說了,程式碼看一眼就懂了;

MvpPresenter 類

public class MvpPresenter {
// View介面
private MvpView mView;

public MvpPresenter(MvpView view) {
    this.mView = view;
}
/**
 * 獲取網路資料
 *
 * @param params 引數
 */
public void getData(String params) {
    //顯示正在載入進度條
    mView.showLoading();
    // 呼叫Model請求資料
    MvpModel.getNetData(params, new MvpCallback() {
        @Override
        public void onSuccess(String data) {
            //呼叫view介面顯示資料
            mView.showData(data);
        }

        @Override
        public void onFailure(String msg) {
            //呼叫view介面提示失敗資訊
            mView.showFailureMessage(msg);
        }

        @Override
        public void onError() {
            //呼叫view介面提示請求異常
            mView.showErrorMessage();
        }

        @Override
        public void onComplete() {
            // 隱藏正在載入進度條
            mView.hideLoading();
        }
    });
}
}
第8步:是不是很刺激?看看自己都寫了什麼❓,下面就是見證奇蹟的時刻,我們的mainActivity中應該如何編寫?佈局檔案很簡單,就是一個線性佈局,裡面一個Button,一個TextView;在Activity中,要例項化Presenter類,並且那幾個方法都在Presenter中實現了哦,在來一個dialog展示框就行了,對不對?上程式碼看看吧,會好理解一些;

MainActivity 類

public class MainActivity extends AppCompatActivity implements MvpView {

private ProgressDialog progressDialog;
private MvpPresenter presenter;
private TextView textview;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textview = findViewById(R.id.textview);
    progressDialog = new ProgressDialog(this);
    progressDialog.setCancelable(false);
    progressDialog.setMessage("正在載入資料");
    presenter = new MvpPresenter(this);

}

/**
 * 點選事件
 * @param view
 */
public void getDatas(View view) {
    presenter.getData("normal");
}

/**
 * 顯示正在載入進度框
 */
@Override
public void showLoading() {
    if (!progressDialog.isShowing()) {
        progressDialog.show();
    }
}

/**
 * 隱藏正在載入進度框
 */
@Override
public void hideLoading() {
    if (progressDialog.isShowing()) {
        progressDialog.dismiss();
    }
}

/**
 * 當資料請求成功後,呼叫此介面顯示資料
 *
 * @param data 資料來源
 */
@Override
public void showData(String data) {
    textview.setText(data);
}

/**
 * 當資料請求失敗後,呼叫此介面提示
 *
 * @param msg 失敗原因
 */
@Override
public void showFailureMessage(String msg) {
    Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}

/**
 * 當資料請求異常,呼叫此介面提示
 */
@Override
public void showErrorMessage() {
    Toast.makeText(this, "網路請求資料出現異常", Toast.LENGTH_SHORT).show();
}

}

四.如上就是實現的過程,這是一個簡單的demo,幫助我們理解和熟悉MVP到底是什麼玩意,真的想要在專案中實踐,還需要花費一番功夫來弄。這個簡單的demo先分享給大家,更多的MVP的內容,我會在下面的文章中更新,歡迎大家一起交流,感謝大家;

最後附上一個GitHub的 下載地址
喜歡的也可以關注下我的微信公眾號“七秒的空間”