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.優點和缺點介紹
優點:
- 模型與視圖完全分離,我們可以修改視圖而不影響模型
- 可以更高效地使用模型,因爲所有的交互都發生在一個地方——Presenter內部
- 我們可以將一個Presenter用於多個視圖,而不需要改變Presenter的邏輯。這個特性非常的有用,因爲視圖的變化總是比模型的變化頻繁。
- 如果我們把邏輯放在Presenter中,那麼我們就可以脫離用戶接口來測試這些邏輯(單元測試)
缺點:
- 由於對視圖的渲染放在了Presenter中,所以視圖和Presenter的交互會過於頻繁。還有一點需要明白,如果Presenter過多地渲染了視圖,往往會使得它與特定的視圖的聯繫過於緊密。一旦視圖需要變更,那麼Presenter也需要變更了。比如說,原本用來呈現Html的Presenter現在也需要用於呈現Pdf了,那麼視圖很有可能也需要變更。
二.看下實現的效果圖
三.接下來是代碼實現的過程
1.從創建開始
- 打開Android Studio 然後新建一個工程;
- 在工程中,新建三個包,分個層,分別是modle、view、presenter
- 思考下我們要實現的功能,模擬網絡請求,然後點擊Button,實現頁面上的TextView的文字改變,這中間我們用Handler模擬一下網絡請求
- 思考一下我們在MVC的時候,Activity要實現的方法:
- 點擊按鈕請求數據
- 當數據請求成功後,調用此接口顯示數據
- 當數據請求失敗後,調用此接口提示
- 當數據請求異常,調用此接口提示
- 顯示正在加載進度框
- 隱藏正在加載進度框
- 根據上面分析在MVC中所要實現的方法,我們來實現在MVP的View層的接口中需要實現這幾個方法;
public interface MvpView {
/**
* 顯示正在加載進度框
*/
void showLoading();
/**
* 隱藏正在加載進度框
*/
void hideLoading();
/**
* 當數據請求成功後,調用此接口顯示數據
* @param data 數據源
*/
void showData(String data);
/**
* 當數據請求失敗後,調用此接口提示
* @param msg 失敗原因
*/
void showFailureMessage(String msg);
/**
* 當數據請求異常,調用此接口提示
*/
void showErrorMessage();
}
- 我們的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();
}
- 如上方法實現後,那我們的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();
}
});
}
}
- 是不是很刺激?看看自己都寫了什麼❓,下面就是見證奇蹟的時刻,我們的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的下載地址
https://github.com/softwareboy92/MVP