前言:Android開發(fā)中有很多的設(shè)計(jì)模式鹿寻,MVP模式無(wú)疑是現(xiàn)在最流行的模式之一。MVP模式有效的降低了項(xiàng)目的復(fù)雜性及耦合性,view與model間完全解耦,通過(guò)presenter作為中間的連接紐帶丢胚,降低了view的復(fù)雜性及view與model耦合程度,使的項(xiàng)目邏輯更加清晰受扳,方便后期的修改與維護(hù)携龟。
MVP:Model--View--Presenter
model:用于數(shù)據(jù)的處理,如請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)等
view:用于將presenter傳遞的數(shù)據(jù)在UI中展示
presenter:將model獲取的數(shù)據(jù)傳遞給view勘高,是view與model聯(lián)系的中間橋梁
注:文中有用到Retrofit2+Rxjava2+Okhttp3實(shí)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)請(qǐng)求相關(guān)的知識(shí)峡蟋,這一篇文章 Android網(wǎng)絡(luò)請(qǐng)求Retrofit2+Rxjava2+Okhttp3的簡(jiǎn)單封裝中有詳細(xì)介紹。
1.Model
(1)定義model基類接口
/**
* Created by ruancw on 2018/5/22.
* model接口基類
*/
public interface IBaseModel {
//獲取Rxjava的disposable
<T>Disposable getObservable(Observable<HttpResponse<T>> observable, String tag);
//網(wǎng)絡(luò)請(qǐng)求接口回調(diào)
interface IOnRequestListener<T>{
void onRequestSuccess(HttpResponse<T> tHttpResponse, String tag);
void onRequestFail(Throwable throwable);
}
}
(2)定義model實(shí)現(xiàn)類
/**
* Created by ruancw on 2018/5/22.
* 通用model實(shí)現(xiàn)類
*/
public class CommonModelImpl implements IBaseModel {
private IOnRequestListener onRequestListener;
public CommonModelImpl(IOnRequestListener onRequestListener) {
this.onRequestListener = onRequestListener;
}
@Override
public <T> Disposable getObservable(Observable<HttpResponse<T>> observable, String tag) {
return DisposableUtils.getDisposable(observable,tag,onRequestListener);
}
}
2.View
定義view接口類
/**
* Created by ruancw on 2018/5/22.
* view基類接口
*/
public interface IBaseView {
//顯示默認(rèn)的進(jìn)度框
void showProgress();
//顯示可設(shè)置提示信息的進(jìn)度框
void showProgress(String message);
//隱藏進(jìn)度框
void hideProgress();
//網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)成功后返回?cái)?shù)據(jù)的方法
void onSuccess(HttpResponse httpResponse, String tag);
//網(wǎng)絡(luò)請(qǐng)求失敗的方法
void onFailed(Throwable throwable);
}
3.Presenter
(1)定義presenter的基類
/**
* Created by ruancw on 2018/5/22.
* presenter基類
*/
public class BasePresenter implements IBaseModel.IOnRequestListener {
//view接口
protected IBaseView mView;
//model接口實(shí)現(xiàn)類
protected CommonModelImpl mModel;
//Rxjava中的類
private CompositeDisposable mCompositeDisposable;
/**
* 綁定view
* @param mView
*/
public void attach(IBaseView mView){
this.mView=mView;
mModel=new CommonModelImpl(this);
}
/**
* 解綁view
*/
public void detach(){
if (mView!=null){
mView=null;
}
}
/**
* 反注冊(cè)rxjava
*/
public void unSubscribe(){
if (mCompositeDisposable != null) {
mCompositeDisposable.dispose();
}
}
/**
* 注冊(cè)rxjava
* @param disposable
*/
public void addSubscription(Disposable disposable) {
//rxjava進(jìn)行注冊(cè)
if (mCompositeDisposable == null) {
mCompositeDisposable= new CompositeDisposable();
}
mCompositeDisposable.add(disposable);
}
@Override
public void onRequestSuccess(HttpResponse httpResponse, String tag) {
if (mView!=null){
mView.hideProgress();
mView.onSuccess(httpResponse,tag);
}
}
@Override
public void onRequestFail(Throwable throwable) {
if (mView!=null){
mView.hideProgress();
mView.onFailed(throwable);
}
}
}
(2)繼承基類BasePresenter(以登錄為例)
/**
* Created by ruancw on 2018/5/23.
* 登錄的presenter實(shí)現(xiàn)類
*/
public class LoginPresenterImpl extends BasePresenter {
public void login(String url, LinkedHashMap<String, String> paramsMap,String tag){
mView.showProgress("正在登錄");
addSubscription(mModel.getObservable(HttpApiService.getInstance().getRemoteData(url,paramsMap),tag));
}
}
注:直接定義的LoginPresenter的實(shí)現(xiàn)類华望,沒有定義ILoginPresenter接口
4.模塊中使用
(1)定義Activity基類
public abstract class BaseMvpActivity<B extends BasePresenter> extends BaseActivity {
public B mPresenter;
@Override
protected void beforeSetContentView() {
mPresenter=initPresenter();
mPresenter.attach(this);
}
protected abstract B initPresenter();
@Override
protected void onDestroy() {
mPresenter.detach();
//mPresenter.unSubscribe();
super.onDestroy();
}
}
(2)LoginActivity繼承BaseMvpActivity
public class LoginActivity extends BaseMvpActivity<LoginPresenterImpl> {
@BindView(R.id.btn_login)
Button btnLogin;
@BindView(R.id.et_account)
ClearEditText etAccount;
@BindView(R.id.et_password)
PasswordView etPassword;
private int userType=1;
private UserBean userBean;
private boolean autoLogin; @Override
protected boolean hasHeadTitle() {
return false;
}
@Override
protected LoginPresenterImpl initPresenter() {
return new LoginPresenterImpl();
}
@Override
protected int getLayoutId() {
return R.layout.activity_login;
}
@Override
protected void initView() {
//獲取上一次填寫的用手機(jī)號(hào)與密碼
userBean=SharePreferencesUtil.getInstance().getUserBean();
if (this.getIntent() != null && this.getIntent().getExtras() != null && this.getIntent().getExtras().containsKey("username")) {
String username = this.getIntent().getExtras().getString("username");
etAccount.setText(username);
} else {
if (userBean != null) {
etAccount.setText(userBean.getAccount());
etPassword.setContent(userBean.getPassword());
}
}
//判斷是否是自動(dòng)登錄
autoLogin=SharePreferencesUtil.getInstance().getBoolean("AUTO_LOGIN");
if (autoLogin){
//自動(dòng)登錄
login();
}
}
/**
* 登錄的方法
*/
private void login() {
etPassword.clearFocus();
//系統(tǒng)的輸入管理器
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(etPassword, InputMethodManager.SHOW_FORCED);
imm.hideSoftInputFromWindow(etPassword.getWindowToken(), 0);
if (TextUtils.isEmpty(etAccount.getText().toString().trim())) {
UIUtil.toast("手機(jī)號(hào)不能為空");
} else if (TextUtils.isEmpty(etPassword.getContent().trim())) {
UIUtil.toast("密碼不能為空");
} else {
LinkedHashMap<String, String> paramsMap = new LinkedHashMap<>();
paramsMap.put("loginName", etAccount.getText().toString().trim());
paramsMap.put("password", etPassword.getContent().trim());
paramsMap.put("userType", userType + "");
mPresenter.login(ApiConstant.LOGIN, paramsMap, "tag");
}
}
@OnClick(R.id.btn_login)
public void onViewClicked() {
//點(diǎn)擊的動(dòng)畫效果
CommonUtil.animateClickView(btnLogin, new CommonUtil.ClickAnimation() {
@Override
public void onClick(View v) {
login();
}
});
}
@Override
public void onSuccess(HttpResponse httpResponse, String tag) {
int code = httpResponse.getStatus();
Log.i("rcw", "httpResponse=" + httpResponse);
Log.i("rcw", "code=" + httpResponse.getStatus());
Log.i("rcw", "data=" + httpResponse.getData());
if (code == 200) {
//存儲(chǔ)賬號(hào)和密碼
userBean=new UserBean();
userBean.setAccount(etAccount.getText().toString().trim());
userBean.setPassword(etPassword.getContent().trim());
userBean.setUsertype(userType);
SharePreferencesUtil.getInstance().saveUserBean(userBean);
//處理返回的data數(shù)據(jù)
String datas = new Gson().toJson(httpResponse.getData());
LoginBean loginBean = new Gson().fromJson(datas, LoginBean.class);
SharePreferencesUtil.getInstance().saveLoginBean(loginBean);
Log.i("rcw", "getDeptName=" + loginBean.getDeptName());
startActivity(new Intent(this, MainActivity.class));
finish();
UIUtil.toast("登錄成功");
} else if (code == 402) {
exitToLogin(this);
} else {
UIUtil.toast(httpResponse.getMessage());
}
}
總結(jié):MVP模式使得View與Model間不能直接交互层亿,通過(guò)中間紐帶Presenter實(shí)現(xiàn)間接聯(lián)系,降低了View與Model間的耦合立美。MVP模式雖好,但如果項(xiàng)目頁(yè)面相對(duì)簡(jiǎn)單方灾,可以直接使用MVC模式實(shí)現(xiàn)建蹄。
如有任何問(wèn)題碌更,歡迎評(píng)論及留言,不勝感激洞慎,謝謝M吹ァ!劲腿!