MVP架構(gòu) + EventBus 構(gòu)建項(xiàng)目這篇文章寫(xiě)得很簡(jiǎn)潔了,感謝作者。
以下內(nèi)容為轉(zhuǎn)抄。
使用MVP架構(gòu) + EventBus 構(gòu)建項(xiàng)目
最近項(xiàng)目重構(gòu),從MVC架構(gòu)換到MVP架構(gòu),好處是多多的,當(dāng)然有利有弊。
利:解耦,提高代碼可維護(hù)性,減輕Activity和Fragment類的重?fù)?dān)。
弊:增加代碼量,增加許多類。
接下來(lái)簡(jiǎn)單的介紹下吊炸天MVP模式,先看一張圖:
Model層:和MVC的Model層一樣,對(duì)數(shù)據(jù)進(jìn)行操作,請(qǐng)求數(shù)據(jù),增刪改查數(shù)據(jù)等。
View:界面層,負(fù)責(zé)展示界面,顯示一張圖片,顯示一個(gè)Dialog等。
Presenter層:View層和Model層的橋梁,因?yàn)樵贛VP架構(gòu)中,View層和Model層完全隔離,View只能通過(guò)Presenter層來(lái)操作數(shù)據(jù)。
EventBus 的使用: Model層 使用 EventBus 向 Presenter層 傳遞數(shù)據(jù)。
添加EventBus 3.0 依賴:
compile 'de.greenrobot:eventbus:3.0.0-beta1'
實(shí)現(xiàn)步驟 (這里以登錄案例來(lái)說(shuō)明)
獲取用戶輸入的數(shù)據(jù),去請(qǐng)求服務(wù)器獲得反饋;這里額外添加進(jìn)入頁(yè)面首先訪問(wèn)服務(wù)器拿一些數(shù)據(jù)。
1:創(chuàng)建 View層和 Presenter層接口,通常包括一些通用接口方法,可以提取到基類接口。
BaseView:
public interface BaseView<T> {
/**
- 給View設(shè)置Presenter
@param presenter
*/
void setPresenter(T presenter);
}
BasePresenter:
public interface BasePresenter {
/**
* 初始化
*/
void start();
/**
* 結(jié)束
*/
void stop();
}
2:然后根據(jù)不同的業(yè)務(wù)創(chuàng)建不同的Contract
LoginContract:
public interface LoginContract {
interface Presenter extends BasePresenter {
/**
* 執(zhí)行登錄動(dòng)作
*/
void login();
}
interface View extends BaseView<Presenter> {
/**
* 顯示服務(wù)器返回的數(shù)據(jù)
* @param serviceInfo
*/
void showServiceInfo(ServiceInfo serviceInfo);
/**
* 獲取用戶輸入的數(shù)據(jù)
* @return 用戶數(shù)據(jù)
*/
String getName();
String getPassword();
/**
* show Toast
* @param text
*/
void showToast(String text);
/**
* 顯示ProgressBar
*/
void showProgressBar();
/**
* 隱藏ProgressBar
*/
void hindProgressBar();
}
}
3:創(chuàng)建登錄LoginActivity實(shí)現(xiàn)LoginContract.View接口,創(chuàng)建LoginPresenter實(shí)現(xiàn)LoginContract.Presenter接口。
LoginActivity:
public class LoginActivity extends AppCompatActivity implements LoginContract.View, View.OnClickListener {
private EditText mEtName;
private EditText mEtPassword;
private Button mBtnLogin;
private ProgressBar mPbProgress;
private TextView mTvServiceInfo;
private LoginContract.Presenter mPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mEtName = (EditText) findViewById(R.id.etName);
mEtPassword = (EditText) findViewById(R.id.etPassword);
mTvServiceInfo = (TextView) findViewById(R.id.tvServiceInfo);
mBtnLogin = (Button) findViewById(R.id.btnLogin);
mPbProgress = (ProgressBar) findViewById(R.id.pbProgress);
mBtnLogin.setOnClickListener(this);
// 綁定Presenter
new LoginPresenter(this);
mPresenter.start();
}
@Override
public void setPresenter(LoginContract.Presenter presenter) {
this.mPresenter = presenter;
}
@Override
public void showServiceInfo(ServiceInfo serviceInfo) {
mTvServiceInfo.setText(serviceInfo.getSeviceInfo());
}
@Override
public String getName() {
return mEtName.getText().toString().trim();
}
@Override
public String getPassword() {
return mEtPassword.getText().toString().trim();
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btnLogin:
mPresenter.login();
break;
}
}
@Override
public void showToast(String text) {
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}
@Override
public void showProgressBar() {
mPbProgress.setVisibility(View.VISIBLE);
}
@Override
public void hindProgressBar() {
mPbProgress.setVisibility(View.GONE);
}
@Override
protected void onDestroy() {
super.onDestroy();
mPresenter.stop();
}
}
LoginPresenter:
public class LoginPresenter implements LoginContract.Presenter {
LoginContract.View mLoginView;
public LoginPresenter(LoginContract.View loginView) {
this.mLoginView = loginView;
mLoginView.setPresenter(this);
}
@Override
public void start() {
EventBus.getDefault().register(this);
new ServiceInfoModelImpl().getServiceInfo();
}
@Subscribe(threadMode = ThreadMode.MainThread)
public void eventBusResult(ResultBean bean) {
// 根據(jù)不同返回?cái)?shù)據(jù),做不同的操作
switch (bean.getAction()){
case ServiceInfoModelImpl.ACTION_GET_SERVICE_INFO:
mLoginView.showServiceInfo((ServiceInfo) bean.getObject());
break;
case UserInfoModelImpl.ACTION_LOGIN:
mLoginView.hindProgressBar();
mLoginView.showToast((String)bean.getObject());
break;
}
}
@Override
public void login() {
UserInfo userInfo = new UserInfo();
String name = mLoginView.getName();
String password = mLoginView.getPassword();
if(TextUtils.isEmpty(name) || TextUtils.isEmpty(name)){
mLoginView.showToast("name or password can not be null");
return;
}
mLoginView.showProgressBar();
userInfo.setName(name);
userInfo.setPassword(password);
// 調(diào)用Model層登錄
new UserInfoModelImpl().login(userInfo);
}
@Override
public void stop() {
EventBus.getDefault().unregister(this);
mLoginView = null;
}
}
總結(jié):
MVP架構(gòu)的優(yōu)點(diǎn)是毋庸置疑的,它適合在一些中大型項(xiàng)目中使用,小項(xiàng)目沒(méi)必要使用;這篇只是本人對(duì)MVP架構(gòu)的淺見(jiàn),如有錯(cuò)誤,那就對(duì)了。