MVP 模式將Activity 中的業務邏輯全部分離出來,讓Activity 只做 UI 邏輯的處理,所有跟Android API無關的業務邏輯由 Presenter 層來完成。 Model 層中包含著具體的數據請求,數據源。 Activity 和Fragment 視為View層,負責處理 UI。 ...
MVP 模式將Activity 中的業務邏輯全部分離出來,讓Activity 只做 UI 邏輯的處理,所有跟Android API無關的業務邏輯由 Presenter 層來完成。
Model 層中包含著具體的數據請求,數據源。
Activity 和Fragment 視為View層,負責處理 UI。
Presenter 為業務處理層,既能調用UI邏輯,又能請求數據。
首先是Model層,Model層用來獲得數據比如說http請求得到的數據,首先定義model層的介面,在BaseModel里添加了兩個介面。
public interface BaseModel {
//這裡寫http請求的介面
void login(String username, String password, onFinishedListener listener);
void exit( onFinishedListener listener);
}
在BaseModelImpl來實現介面里的方法,用來獲得數據這裡我模擬了耗時操作來獲取數據並回調介面onFInishListener
public class BaseModelImpl implements BaseModel {
//這裡寫http請求
@Override
public void login(final String username,final String password,final onFinishedListener listener) {
new Handler().postDelayed(new Runnable() {
@Override public void run() {
boolean error = false;
if (TextUtils.isEmpty(username)){
listener.onError("用戶名不存在");//model層裡面回調listener
error = true;
return;
}
if (TextUtils.isEmpty(password)){
listener.onPasswordError();
error = true;
return;
}
if (!error){
// 返回方法名和http請求的結果
listener.onSuccess("login","{}");
}
}
}, 2000);
}
@Override
public void exit(final onFinishedListener listener) {
new Handler().postDelayed(new Runnable() {
@Override public void run() {
// 返回方法名和http請求的結果
listener.onSuccess("exit","{}");
}
}, 2000);
}
}
介面onFInishListener是獲得數據完成時根據返回結果進行不同的處理
public interface onFinishedListener {
//通用錯誤提示
void onError(String error);
//需要特殊處理的錯誤提示
void onUsernameError();
void onPasswordError();
/**
*
* @param way 方法名
* @param result 返回結果
*/
void onSuccess(String way,String result);
}
BaseView是改變UI層的介面,在Activity或者Fragment調用改變UI,BaseView的實現在activity或者fragment實現
public interface BaseView {
void showProgress();
void hideProgress();
void setUsernameError();
void setPasswordError();
void setError(String error);
void success(String way, String result);
}
BasePresentesenter的作用連接Model 層和View
public interface BasePresenter {
void login(String username, String password);
void exit();
void onDestroy();
}
下麵是實現 BasePresentesenter的方法
public class BasePresenterImpl implements BasePresenter, onFinishedListener {
private BaseView baseView;
private BaseModel baseModel;
public BasePresenterImpl(BaseView baseView){
this.baseView = baseView;
this.baseModel = new BaseModelImpl();
}
@Override
public void login(String username, String password) {
if (baseView != null) {
baseView.showProgress();
}
baseModel.login(username, password, this);
}
@Override
public void exit() {
if (baseView != null) {
baseView.showProgress();
}
baseModel.exit(this);
}
@Override
public void onDestroy() {
baseView = null;
}
@Override
public void onError(String error) {
if (baseView != null) {
baseView.setError(error);
baseView.hideProgress();
}
}
@Override
public void onUsernameError() {
if (baseView != null) {
baseView.setUsernameError();
baseView.hideProgress();
}
}
@Override
public void onPasswordError() {
if (baseView != null) {
baseView.setPasswordError();
baseView.hideProgress();
}
}
@Override
public void onSuccess(String way, String result) {
if (baseView != null) {
baseView.success(way,result);
baseView.hideProgress();
}
}
}
UI層實現BaseView的介面下麵是實例
public class MainActivity extends AppCompatActivity implements BaseView,View.OnClickListener {
private ProgressBar progress;
private BasePresenter presenter;
private Button button;
private EditText username;
private EditText password;
private Button exit;
private CustomDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressDialog = new CustomDialog(this, R.style.CustomDialog);
progress = (ProgressBar)findViewById(R.id.progress);
presenter = new BasePresenterImpl(this);
username = (EditText) findViewById(R.id.username);
password = (EditText) findViewById(R.id.password);
button = (Button)findViewById(R.id.button);
button.setOnClickListener(this);
exit = (Button)findViewById(R.id.exit);
exit.setOnClickListener(this);
}
@Override
public void showProgress() {
progressDialog.show();
}
@Override
public void hideProgress() {
progressDialog.cancel();
}
@Override
public void setUsernameError() {
username.setError(getString(R.string.username_error));
}
@Override
public void setPasswordError() {
password.setError(getString(R.string.password_error));
}
@Override
public void setError(String error) {
Toast.makeText(this,error,Toast.LENGTH_SHORT).show();
}
@Override
public void success(String way, String result) {
Toast.makeText(this,way,Toast.LENGTH_SHORT).show();
//根據調用的介面,更新成功的ui
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.button:
presenter.login(username.getText().toString(), password.getText().toString());
break;
case R.id.exit:
presenter.exit();
break;
}
}
@Override
protected void onDestroy() {
presenter.onDestroy();
super.onDestroy();
}
}
在baseView定義不同的錯誤,在Activity中處理他們來改變ui,比如說用戶名錯誤我們就調用setUsernameError的方法來提示用戶用戶名錯誤,如果調用成功時會回調success方法,第一個參數是調用方法的名稱,用來區分各個介面調用成功之後的不同處理,第二個參數result是返回的數據,用來處理或者填充列表。
github的網址:https://github.com/tempest1/androidMvp