MVP介紹:數據庫
MVP 全稱:Model-View-Presenter ;MVP 是從經典的模式MVC演變而來,它們的基本思想有相通的地方:Controller/Presenter負責邏輯的處理,Model提供數據,View負責顯示。網絡
RxJava介紹:框架
RxJava 在 GitHub 主頁上的自我介紹是 "a library for composing asynchronous and event-based programs using observable sequences for the Java VM"(一個在 Java VM 上使用可觀測的序列來組成異步的、基於事件的程序的庫)。這就是 RxJava ,歸納得很是精準。對RxJava不熟悉的能夠看下https://gank.io/post/560e15be2dca930e00da1083這篇文章(我也不是很熟悉,拿來就用而已,手動攤手)。
異步
Retrofit介紹:async
public interface BaseView { /** * 顯示正在加載view */ void showLoading(); /** * 關閉正在加載view */ void hideLoading(); /** * 顯示提示 * @param msg */ void showToast(String msg, int length); /** * 顯示請求錯誤提示 */ void showErr(String errMsg); /** * 獲取上下文 * @return 上下文 */ Context getContext(); }
好比如今有個登陸需求須要實現,新建一個LoginView,並繼承BaseView,使各功能View能自行實現本身的需求;ide
public interface LoginView extends BaseView { void loginSuccess(); void loginFailure(); }
OK,咱們如今有了登陸模塊的View了,那麼,咱們能夠在相關登陸模塊的Activitiy,Fragment上實現該LoginView,例如:post
public class LoginActivity extends BaseActivity<LoginPresenter> implements LoginView{ @Override public void loginSuccess() { } @Override public void loginFailure() { } }
好的,那麼咱們的LoginActivity就實現了咱們的LoginView功能了,BaseActivity待會會介紹;ui
View大概就這麼多,能夠根據具體的功能需求添加刪除;this
二、Presenter層:由上文提到的,負責邏輯處理;spa
一樣,新建一個BasePresenter類,由於presenter層級的操做是基於View層的,咱們須要在BasePresenter每一步操做前判斷咱們的view是否存在;
public class BasePresenter<V extends BaseView> { private V view; /** * 綁定view,通常在初始化中調用該方法 */ public void attachView(V view){ this.view = view; } /** * 斷開view,通常在onDestroy中調用 */ public void detachView(){ this.view = null; } /** * 是否與View創建鏈接 * 每次調用業務請求的時候都要出先調用方法檢查是否與View創建鏈接 */ public boolean isViewAttached(){ return view != null; } /** * 獲取鏈接的view */ public V getView(){ return this.view; } public Context getContext(){ return this.view.getContext(); } }
如上圖,咱們能夠經過isViewAttached判斷view是否存在,若是view已銷燬,咱們的邏輯處理也不必繼續下去,進行相對應的銷燬工做便可;
OK,一樣咱們來實現功能Presenter,按照View的如今,咱們也實現一個登陸模塊的Presenter,新建一個LoginPresenter抽象類,並將對應的View以泛型參數聲明:
public abstract class LoginPresenter extends BasePresenter<LoginView> { /** * 登陸方法 */ public abstract void login(String phoneNum, String password); }
而後,咱們將具體實現LoginPresenter,新建一個LoginPresenterImpl類,並繼承LoginPresenter;
public class LoginPresenterImpl extends LoginPresenter { @Override public void login(String phoneNum, String password) { if (isViewAttached()) { // 實現Login功能 } } }
Ok,如今咱們回頭來看LoginActivity,將咱們對應功能Presenter以泛型參數傳入
LoginActivity extends BaseActivity<LoginPresenter>
三、來看看BaseActivity,直接上代碼:
public abstract class BaseActivity<T extends BasePresenter> extends FragmentActivity implements BaseView { protected T mPresenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setupContentView(); initView(); createPresenterAndAttachView(); } @Override protected void onDestroy() { super.onDestroy(); if (mPresenter != null) { mPresenter.detachView(); } } @Override public void showLoading() { Views.getInstance().showTipDialog(Views.TIPDIALOG_LOADING, this); } @Override public void hideLoading() { Views.getInstance().closeTipDialog(); } @Override public void showToast(String msg, int length) { runOnUiThread(() -> Toast.makeText(getContext(), msg, length).show()); } @Override public void showErr(String errMsg) { showToast(errMsg, Toast.LENGTH_LONG); } @Override public Context getContext() { return BaseActivity.this; } protected abstract void createPresenterAndAttachView(); protected abstract void setupContentView(); protected abstract void initView(); }
BaseActivity實現BaseView,將公共功能實現一下,同時咱們的Presenter在onDestroy()上將view解綁,同時我也寫了幾個抽象方法,createPresenterAndAttachView()在該方法中建立Presenter並進行view的鏈接工做,
其餘就無關緊要啦,根據本身的想法走吧。
好了,咱們如今差很少能夠用起來了。來看看LoginActivity的具體實現:
public class LoginActivity extends BaseActivity<LoginPresenter> implements LoginView, View.OnClickListener { @Override protected void createPresenterAndAttachView() { // 實例化Presenter mPresenter = new LoginPresenterImpl(); // view創建鏈接 mPresenter.attachView(this); } @Override protected void setupContentView() { setContentView(R.layout.activity_login); } @Override protected void initView() { // 初始化界面 } @Override public void loginSuccess() { // 登陸成功 } @Override public void loginFailure() { // 登陸失敗 } @Override public void onClick(View view) { } }
四、上面彷佛還少了個Model層,Model層主要是負責數據,如網絡訪問,數據庫查詢等操做,該層沒有進一步進行封裝了,先來看看Presenter層裏是怎樣跟Model層交互的;
public class LoginPresenterImpl extends LoginPresenter { @Override public void login(String phoneNum, String password) { if (isViewAttached()) { Map<String, Object> params = new HashMap<>(); params.put("phoneNum", phoneNum); params.put("password", password); UserModel.login(getContext(), params, new Callback<LoginResponse>() { @Override public void onSuccess(LoginResponse data) { } @Override public void onFailure(int errCode, String msg) { } }); } } }
如上圖,在Presenter具體的邏輯實現中,咱們只是簡單的調用了Model層進行具體的數據操做;
讓咱們看看UserModel是怎樣作的:
/** * 用戶Model */ public final class UserModel { /** * 登陸 * @param params * @param callback */ public static void login(Context context, Map<String, Object> params, Callback<LoginResponse> callback) { RetrofitManager.getInstance().createService(UserApi.class).login(params) .compose(RetrofitManager.getInstance().ioMainSchedulers()) .subscribe(new BaseObserver<>(context, callback)); } }
LoginResponse是服務端返回的實體數據,具體如何造就看你服務端具體返回什麼了;
Callback是一個通用的接口,以下:
public interface Callback<T> { /** * 數據請求成功 * * @param data */ void onSuccess(T data); /** * 使用網絡API接口請求方式時,雖然已經請求成功可是由 * 於{@code msg}的緣由沒法正常返回數據。 */ void onFailure(int errCode, String msg); }
五、終於到RxJava和Retrofit的使用了,RetrofitManager是一個Retrofit管理類
/** * Retrofit管理類 */ public final class RetrofitManager { private Retrofit retrofit; public static RetrofitManager getInstance() { return RetrofitHelper.manager; } private RetrofitManager() { retrofit = new Retrofit.Builder() .baseUrl(HttpConstants.BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build(); } private static class RetrofitHelper { private static final RetrofitManager manager = new RetrofitManager(); } public <T> T createService(Class<T> clazz) { return retrofit.create(clazz); } public <T> ObservableTransformer<T, T> ioMainSchedulers() { return upstream -> upstream.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()); } }
主要就是實現一個單例模式,而後配合RxJava進行使用,以下login接口:
public interface UserApi { @FormUrlEncoded @POST(HttpConstants.LOGIN) Observable<BaseResponse<LoginResponse>> login(@FieldMap Map<String, Object> params); }
Retrofit+RxJava主要是接口返回參數爲RxJava的Observable,就是這麼簡單,深刻的我也還沒去研究,先用起來吧。
Ok,大概就是這樣了。這樣的話,咱們的各層級進行了應有的解耦,代碼也乾淨了不少。可是,代碼量我以爲是多了的。
本身隨手記錄的一些內容,至關因而複習了下RxJava,Retrofit的使用和Mvp的概念,不喜勿噴。