本章節(jié) 我門將運用上一講Retrofit + RxJava + OkHttp 的簡單封裝的網(wǎng)絡(luò)請求框架
前言
最開始我學習android的時候只會用MVC,MVC相信大家都知道,缺點很明顯,代碼結(jié)構(gòu)很亂,開發(fā)玩一個功能遣铝,幾個月后再回來要改什么功能,一看代碼.我**X******這TM是誰寫的代碼(明明就是自己寫的)莉擒,糾其原因就是因為Activity中同時擁有業(yè)務(wù)和UI邏輯代碼酿炸,不排除還可能存在某些不良編程習慣導致。
那么什么是MVP架構(gòu)?
MVP代表Model涨冀,View和Presenter梁沧。
View層負責處理用戶事件和視圖部分的展示。在Android中蝇裤,它可能是Activity或者Fragment類廷支。
Model層負責訪問數(shù)據(jù)。數(shù)據(jù)可以是遠端的Server API栓辜,本地數(shù)據(jù)庫或者SharedPreference等恋拍。
Presenter層是連接(或適配)View和Model的橋梁。
這么說可能不太好理解 我們看圖說話....(為了使你更好理解 圖片上已經(jīng)備注好了順序和過程)
注意:以下代碼均取自Fazhi項目wanggang老師的教學代碼 最后我會提供代碼供大家下載 不用擔心!
第一步 準備工作 定義基類接口
1.定義BaseView接口 一些公用的回調(diào)
public interface BaseView {
void showError(String error);// 展示錯誤的回調(diào)
void showLoading();// 展示開始請求的Loading
void hideLoading();// 隱藏開始請求的Loading
Context getContext();// 用來獲取Context上下文
}
2.定義BaseModel接口
public interface BaseModel {
// 暫時為空 方便日后更改統(tǒng)一的東西
}
3.定義BasePresenter接口
public interface BasePresenter{
// 暫時為空
}
4.定義BaseActivity藕甩、BaseFragment施敢、Bean類
這些不用在說了把 隨便你門怎么搞 不知道搞就空著放在哪里 預留 相信我總有天你要用的
第二步 繼承第一步定義的基類周荐,并拓展一些該業(yè)務(wù)需求的方法
1.繼承基礎(chǔ)的BaseView
定義出不同業(yè)務(wù)需求下的拓展View接口,為什么我門不直接在BaseView接口中就定義好呢? 主要是為了之后的拓展僵娃,基類我門只做公共的事情概作,而這里很明顯,不同的請求成功后需要返回的參數(shù)的數(shù)量不一樣和參數(shù)類型也可能不同默怨。
在這里我門主要是講Login需求讯榕,那么登陸成功后,需要成功的回調(diào)并且傳遞成功后的參數(shù)給activity匙睹,去顯示提示用戶或者更新UI愚屁,所以我門返回UserBean這個實體類。
public interfaceI LoginView extends BaseView{
void showHint(UserBean userBean);
}
2.繼承基礎(chǔ)的BaseModel
Model負責訪問數(shù)據(jù) 那么我門定義好登陸的請求接口 用來返回Observable<BaseResponse<UserBean>>這個可觀察者對象
public interface LoginModel extends BaseModel {
Observable<BaseResponse<UserBean>>(String username, String passwrod);//登陸
}
3.繼承基礎(chǔ)的BasePresenter
Presenter連接View和Model的橋梁 具體待會看代碼就知道為什么了
public interface LoginPresenter {
void login(String username, String passwrod);//登陸
}
第三步 實現(xiàn)剛才我門拓展的接口
1.實現(xiàn)Model中的login方法痕檬,調(diào)用我門之前封裝好的Retrofit + Rxjava + OkHttp請求庫霎槐,完成請求并返回Observable這個可觀察對象,Presenter這個中間人拿到了觀察者對象就可以處理訂閱結(jié)果梦谜。
public class LoginModelImple implements ILoginModel {
@Override
public Observable<BaseResponse<UserBean>> login(String username, String passwrod) {
HashMap<String, Object> map = new HashMap<>();
map.put("username", username);
map.put("password", passwrod);
RequestBody requestBody = NetRequest.generateReqBody(map);
return NetRequest.getInstance().getApi().userLogin(requestBody);
}
}
2.實現(xiàn)PresenterImpl層有具體的請求邏輯(比如事先判斷參數(shù)是否為空這些)丘跌,并且還持有module和view層,可以在命令Model請求完結(jié)果后唁桩,把結(jié)果由View回調(diào)給Activity處理成功失敗的操作碍岔,是名副其實的橋梁....
public class LoginPresenterImpl implements ILoginPresenter {
private ILoginModel model;
private ILoginView view;
public LoginPresenterImpl(ILoginView view) {
this.model = new LoginModelImple();
this.view = view;
}
@Override
public void login(String username, String passwrod) {
if(TextUtils.isEmpty(username)){
view.showError("賬號不能為空");
return;
}
if(TextUtils.isEmpty(passwrod)){
view.showError("密碼不能為空");
return;
}
Observable<BaseResponse<UserBean>> login = model.login(username, passwrod);
login.compose(RxHelper.schedulers())
.compose(RxHelper.transform())
.subscribe(new NetSubscriber<UserBean>() {
@Override
public BaseView getView() {
return view;
}
@Override
public void onNext(UserBean userBean) {
// 保存值 以備下次驗證使用
LocalData.putSessionKey(userBean.getSession_key());
LocalData.putUserID(userBean.getUser_id());
// 跳轉(zhuǎn)到首頁
// 登陸成功 回調(diào)Activity
view.showHint(userBean);
}
});
}
}
3.最后當然是看看Activity中到底有多小的腰圍啦!(驚訝!~~好干凈整潔的Activity)
注意View層是Activity實現(xiàn)的 用來接收LoginPresenterImpl這個橋梁中間人反回給我門的結(jié)果哦!
public class LoginActivity extends BaseActivity implements ILoginView {
@BindView(R.id.login_et_phone)
EditText loginEtPhone;
@BindView(R.id.login_et_pasd)
EditText loginEtPasd;
private LoginPresenterImpl loginPresenter;
private LoadingDialog loadingDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.bind(this);
loginPresenter = new LoginPresenterImpl(this);
}
@OnClick(R.id.login_btn_login)
public void onClick() {
loginPresenter.login(loginEtPhone.getText().toString(), loginEtPasd.getText().toString());
}
@Override
public void showHint(UserBean userBean) {
ToastUtils.showToast(this, userBean.getNickname());
}
@Override
public void showError(String error) {
ToastUtils.showErrorToast(this, error);
}
@Override
public void showLoading() {
loadingDialog = new LoadingDialog(this);
loadingDialog.show();
}
@Override
public void hideLoading() {
loadingDialog.dismiss();
}
@Override
public Context getContext() {
return this;
}
}
老鐵們,有了第一次寫帖子朵夏,自然也有第二次是把?
fazhi項目框架 Git下載 (向作者wanggang老師致敬)