MVC、MVP概念網(wǎng)上都有,不再重復(fù),這里直接展示MVP架構(gòu)怎么搭建的。不考慮架構(gòu),正常我們寫的代碼一般都是MVC架構(gòu)的。以簡單的登錄界面為例:
public class MainActivity extends AppCompatActivity {
private TextView tv_result;
private EditText et_input;
private Button btn_login;
//進度條
ProgressDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_result = findViewById(R.id.tv_result);
et_input = findViewById(R.id.et_input);
btn_login = findViewById(R.id.btn_login);
// 初始化進度條
progressDialog = new ProgressDialog(this);
progressDialog.setCancelable(false);
btn_login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getData(et_input.getText().toString().trim());
}
});
}
/**
* 模擬網(wǎng)絡(luò)請求
* @param input
*/
public void getData(final String input) {
progressDialog.show();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
switch (input) {
case "success":
tv_result.setText("登錄成功");
break;
case "fail":
tv_result.setText("請求失?。簠?shù)有誤");
break;
case "error":
tv_result.setText("請求報錯: 500");
break;
}
progressDialog.dismiss();
}
},1000);
}
}
我們可以看到,UI處理、業(yè)務(wù)邏輯、數(shù)據(jù)請求都在一起,當(dāng)頁面邏輯越復(fù)雜時,我們activity中代碼越多,后面迭代維護時越麻煩,當(dāng)有邏輯相似的頁面時,我們還要重新寫一遍,造成代碼冗余,復(fù)用性差,這就需要用到我們的MVP架構(gòu),下面我們將代碼進行優(yōu)化:
先新建網(wǎng)絡(luò)請求的響應(yīng)
public interface IBaseCallback{
/**
* 數(shù)據(jù)請求成功
* @param data 請求結(jié)果
*/
void onSuccess(String data);
/**
* 網(wǎng)絡(luò)請求成功,但數(shù)據(jù)請求失敗(如參數(shù)錯誤,數(shù)據(jù)解析報錯,后臺報錯等)
* @param msg 錯誤原因
*/
void onFailure(String msg);
/**
* 網(wǎng)絡(luò)請求失敗
* @param error 失敗原因
*/
void onError(String error);
/**
* 當(dāng)請求數(shù)據(jù)結(jié)束時,無論結(jié)果如何,都會走的方法,一般用于加載框顯示隱藏控制
*/
void onComplete();
}
將網(wǎng)絡(luò)請求單獨封裝成model
public class MvpModel {
/**
* 獲取網(wǎng)絡(luò)接口數(shù)據(jù)
* @param param 請求參數(shù)
* @param callback 數(shù)據(jù)回調(diào)接口
*/
public static void getNetData(final String param, final IBaseCallback<String> callback){
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
switch (param){
case "success":
callback.onSuccess("登錄成功");
break;
case "fail":
callback.onFailure("請求失?。簠?shù)有誤");
break;
case "error":
callback.onError("請求報錯: 500");
break;
}
callback.onComplete();
}
},1000);
}
}
創(chuàng)建Presenter進行業(yè)務(wù)邏輯處理
public class MvpPresenter {
private MvpView mvpView;
/**
* 獲取綁定的mvpView
*/
public MvpView getMvpView() {
return mvpView;
}
/**
* 綁定view,一般在初始化中調(diào)用該方法,為避免網(wǎng)絡(luò)請求后view被銷
* 毀造成空指針,所以將presenter與view綁定
*/
public void attachView(MvpView mvpView) {
this.mvpView = mvpView;
}
/**
* 斷開view,一般在onDestroy中調(diào)用
*/
public void detachView() {
this.mvpView = null;
}
/**
* 檢測是否與View建立連接,避免view被銷毀后空指針
* 每次調(diào)用業(yè)務(wù)請求的時候都要出先調(diào)用方法檢查是否與View建立連接
*/
public boolean isViewAttached() {
return mvpView != null;
}
public void getData(String params) {
getMvpView().showLoading();
MvpModel.getNetData(params, new IBaseCallback<String>() {
@Override
public void onSuccess(String data) {
if (isViewAttached())
getMvpView().showData(data);
}
@Override
public void onFailure(String msg) {
if (isViewAttached())
getMvpView().showFailureMessage(msg);
}
@Override
public void onError(String error) {
if (isViewAttached())
getMvpView().showErrorMessage(error);
}
@Override
public void onComplete() {
if (isViewAttached())
getMvpView().hideLoading();
}
});
}
}
新建view的接口,然后用activity實現(xiàn)
public interface MvpView {
/**
* 當(dāng)數(shù)據(jù)請求成功后,調(diào)用此接口顯示數(shù)據(jù)
*/
void showData(String data);
/**
* 當(dāng)網(wǎng)絡(luò)請求成功,但有其他報錯時后,調(diào)用此接口提示
*/
void showFailureMessage(String msg);
/**
* 當(dāng)網(wǎng)絡(luò)請求失敗,調(diào)用此接口提示
*/
void showErrorMessage(String error);
/**
* 顯示正在加載進度框
*/
void showLoading();
/**
* 隱藏正在加載進度框
*/
void hideLoading();
}
public class MainActivity extends AppCompatActivity implements MvpView{
private TextView tv_result;
private EditText et_input;
private Button btn_login;
MvpPresenter mvpPresenter;
//進度條
ProgressDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_result = findViewById(R.id.tv_result);
et_input = findViewById(R.id.et_input);
btn_login = findViewById(R.id.btn_login);
// 初始化進度條
progressDialog = new ProgressDialog(this);
progressDialog.setCancelable(false);
mvpPresenter = new MvpPresenter();
mvpPresenter.attachView(this);
btn_login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mvpPresenter.getData(et_input.getText().toString().trim());
}
});
}
@Override
public void showData(String data) {
tv_result.setText(data);
}
@Override
public void showFailureMessage(String msg) {
tv_result.setText(msg);
}
@Override
public void showErrorMessage(String error) {
tv_result.setText(error);
}
@Override
public void showLoading() {
if (!progressDialog.isShowing()){
progressDialog.show();
}
}
@Override
public void hideLoading() {
if (progressDialog.isShowing()){
progressDialog.dismiss();
}
}
}
這樣就將我們平常寫的MVC架構(gòu)的代碼,改為了MVP的,后面還可以將presenter抽取基類,view抽取基類,將代碼更簡化