mvp关联activity生命周期_Rxjava+Retrofit统一异常处理与生命周期管理
一、引入
9102年了,終于準備用mvp來重構一下了之前寫過Mvc模式下的Retrofit統一異常處理,這次用MVP重構過程中發現諸多不足之處,便重新進行修繕,使其在我看來更加優雅emmmmmm,文中不足之處,還望諸位同仁多多指點。推薦閱讀:終于有人把 【移動開發】 從基礎到實戰的全套視頻弄全了
二、基本流程描述
BaseView
BaseView接口定義了可能用到的方法,特別是addSubscribe,用來管理RxJava生命周期。
1public interface BaseView {23 /**4 * 顯示吐司5 *6 * @param msg 提示消息7 */8 void showMsg(String msg);9 10 /** 11 * 顯示加載動畫 12 */ 13 void showProgress(); 14 15 /** 16 * 顯示提示 17 */ 18 void showTip(@QMUITipDialog.Builder.IconType int iconType, CharSequence tipWord); 19 20 /** 21 * 關閉加載動畫 22 */ 23 void hideProgress(); 24 25 /** 26 * 關閉提示 27 */ 28 void hideTip(); 29 30 /** 31 * 跳轉頁面 32 */ 33 void startActivitySample(Class<?> cls); 34 35 /** 36 * Rx事件管理 37 * 38 * @param subscription 39 */ 40 void addSubscribe(Disposable subscription); 41 42}BasePresenter
BasePresenter方法中只定義了綁定View與解綁View的接口
1public interface BasePresenter<T extends BaseView> { 2 3 void attachView(T view); 4 5 void detachView(); 6}BaseActivity/Fragment
這個類是封裝了一些常用方法,并且實現了BaseView的全部接口。 并且預留了兩個用于mvp模式的空方法
1@Override2protected void onCreate(@Nullable Bundle savedInstanceState) {3 super.onCreate(savedInstanceState);4 initContentView(R.layout.activity_base);5 setContentView(getLayout());6 mTopBar = (QMUITopBar) findViewById(R.id.base_topbar);7 ButterKnife.bind(this);8 mContext = this;9 mSwipeBackLayout = getSwipeBackLayout(); 10 if (isStartSwipeBack()) { 11 mSwipeBackLayout.setEdgeTrackingEnabled(SwipeBackLayout.EDGE_LEFT); 12 } else { 13 mSwipeBackLayout.setEnableGesture(false); 14 } 15 AppManager.addActivity(this); 16 // 在此處調用綁定Presenter方法 17 initPresenter(); 18 initEventAndData(); 19} 20 21@Override 22protected void onDestroy() { 23 unSubscribe(); 24 removePresenter(); 25 AppManager.removeActivity(this); 26 super.onDestroy(); 27} 28 29protected void initPresenter() { 30 31} 32 33protected void removePresenter() { 34 35}BaseMvpActivity/Fragment
實現了BaseActivity/Fragment中的預留方法
1public abstract class BaseMvpActivity<T extends BasePresenter> extends BaseActivity {23 protected T mPresenter;45 @Override6 protected void initPresenter() {7 mPresenter = createPresenter();8 if (mPresenter != null) {9 mPresenter.attachView(this); 10 } 11 } 12 13 @Override 14 protected void removePresenter() { 15 if (mPresenter != null) { 16 mPresenter.detachView(); 17 } 18 } 19 20 /** 21 * 創建Presenter 22 * 23 * @return 24 */ 25 protected abstract T createPresenter(); 26 27}SamplePresenter
SamplePresenter實現了BasePresenter中的綁定view與解綁view
BaseResponse
RESTful API的基類,看下代碼很容易明白,但是需要注意下isOk(BaseView view)方法
1public class BaseResponse<T> {234 private int statusCode;5 private String message;6 private T data;78 public boolean isOk(BaseView view) {9 // statusCode == 1服務器請求成功 10 if (statusCode == 1) { 11 return true; 12 } else { 13 // 服務器正常請求返回的錯誤 14 NetworkError.error(view, new ServerException(statusCode, message)); 15 return false; 16 } 17 } 18 19 // get/set... 20}NetworkError
根據不同的標志統一處理異常以及服務器返回的錯誤
1public class NetworkError {23 public static void error(BaseView view, Throwable throwable) {4 RetrofitException.ResponeThrowable responeThrowable = RetrofitException.retrofitException(throwable);5 // 此處可以通過判斷錯誤代碼來實現根據不同的錯誤代碼做出相應的反應6 switch (responeThrowable.code) {7 case RetrofitException.ERROR.UNKNOWN:8 case RetrofitException.ERROR.PARSE_ERROR:9 case RetrofitException.ERROR.NETWORD_ERROR: 10 case RetrofitException.ERROR.HTTP_ERROR: 11 case RetrofitException.ERROR.SSL_ERROR: 12 view.showMsg(responeThrowable.message); 13 break; 14 case -1: 15 // 跳轉到登陸頁面 16 view.startActivitySample(LoginActivity.class); 17 break; 18 default: 19 view.showMsg(responeThrowable.message); 20 break; 21 } 22 } 23}ServerException
自定義服務器異常
1public class ServerException extends RuntimeException { 2 3 public int code; 4 5 public ServerException(int code, String message) { 6 super(message); 7 this.code = code; 8 } 9}RetrofitException
自定義網絡異常,獲取錯誤原因
1public class RetrofitException {23 private static final int UNAUTHORIZED = 401;4 private static final int FORBIDDEN = 403;5 private static final int NOT_FOUND = 404;6 private static final int REQUEST_TIMEOUT = 408;7 private static final int INTERNAL_SERVER_ERROR = 500;8 private static final int BAD_GATEWAY = 502;9 private static final int SERVICE_UNAVAILABLE = 503; 10 private static final int GATEWAY_TIMEOUT = 504; 11 12 public static ResponeThrowable retrofitException(Throwable e) { 13 ResponeThrowable ex; 14 if (e instanceof HttpException) { 15 HttpException httpException = (HttpException) e; 16 ex = new ResponeThrowable(e, ERROR.HTTP_ERROR); 17 switch (httpException.code()) { 18 case UNAUTHORIZED: 19 case FORBIDDEN: 20 case NOT_FOUND: 21 case REQUEST_TIMEOUT: 22 case GATEWAY_TIMEOUT: 23 case INTERNAL_SERVER_ERROR: 24 case BAD_GATEWAY: 25 case SERVICE_UNAVAILABLE: 26 default: 27 ex.message = "網絡錯誤"; 28 break; 29 } 30 return ex; 31 } else if (e instanceof ServerException) { 32 // 服務器下發的錯誤 33 ServerException resultException = (ServerException) e; 34 ex = new ResponeThrowable(resultException, resultException.code); 35 ex.message = resultException.getMessage(); 36 return ex; 37 } else if (e instanceof JsonParseException 38 || e instanceof JSONException 39 || e instanceof ParseException) { 40 ex = new ResponeThrowable(e, ERROR.PARSE_ERROR); 41 ex.message = "解析錯誤"; 42 return ex; 43 } else if (e instanceof ConnectException 44 || e instanceof SocketTimeoutException 45 || e instanceof UnknownHostException) { 46 ex = new ResponeThrowable(e, ERROR.NETWORD_ERROR); 47 ex.message = "連接失敗"; 48 return ex; 49 } else if (e instanceof SSLHandshakeException) { 50 ex = new ResponeThrowable(e, ERROR.SSL_ERROR); 51 ex.message = "證書驗證失敗"; 52 return ex; 53 } else { 54 ex = new ResponeThrowable(e, ERROR.UNKNOWN); 55 ex.message = "未知錯誤"; 56 return ex; 57 } 58 } 59 60 61 /** 62 * 約定異常 63 */ 64 class ERROR { 65 /** 66 * 未知錯誤 67 */ 68 public static final int UNKNOWN = 1000; 69 /** 70 * 解析錯誤 71 */ 72 public static final int PARSE_ERROR = 1001; 73 /** 74 * 網絡錯誤 75 */ 76 public static final int NETWORD_ERROR = 1002; 77 /** 78 * 協議出錯 79 */ 80 public static final int HTTP_ERROR = 1003; 81 /** 82 * 證書出錯 83 */ 84 public static final int SSL_ERROR = 1005; 85 } 86 87 public static class ResponeThrowable extends Exception { 88 public int code; 89 public String message; 90 91 public ResponeThrowable(Throwable throwable, int code) { 92 super(throwable); 93 this.code = code; 94 } 95 } 96}RetrofitClient
使用單例封裝的Retrofit,這里就不寫了,相信大家都寫過
ServiceApi
這個是Api接口與10對應,這里用的Observable,感覺沒必要用Flowable,用Flowable的話下面12這個就不是這么寫了
1public interface ServiceApi { 2 3 /** 4 * 測試接口 5 */ 6 @POST("test") 7 Observable<BaseResponse<LoginModel>> login(); 8} 1RetrofitSubscriber(Observer)通過BaseView調用在BaseActivity/Fragment中實現的addSubscribe將Disposable添加到CompositeDisposable中,在頁面銷毀時先中斷請求,以免造成view銷毀了還去調用導致空指針異常。并且根據Observer的接口通過BaseView來處理加載動畫(在BaseActivity/Fragment中實現)。
1public abstract class RetrofitSubscriber<T> implements Observer<T> {23 private final WeakReference<BaseView> mView;45 public RetrofitSubscriber(BaseView view) {6 super();7 mView = new WeakReference<>(view);8 }9 10 @Override 11 public void onSubscribe(Disposable d) { 12 if (!NetworkUtils.isConnected()) { 13 mView.get().showMsg("網絡未連接,請檢查網絡"); 14 d.dispose(); 15 } else { 16 mView.get().showProgress(); 17 mView.get().addSubscribe(d); 18 } 19 } 20 21 @Override 22 public void onComplete() { 23 if (mView != null && mView.get() != null) { 24 mView.get().hideProgress(); 25 } 26 } 27 28 @Override 29 public void onError(Throwable e) { 30 if (mView != null && mView.get() != null) { 31 mView.get().hideProgress(); 32 } 33 onNetError(e); 34 } 35 36 @Override 37 public void onNext(T response) { 38 if (response instanceof BaseResponse) { 39 if (((BaseResponse) response).isOk(mView.get())) { 40 onSuccess(response); 41 } else { 42 onServiceError(response); 43 } 44 } else { 45 onOtherSuccess(response); 46 } 47 } 48 49 /** 50 * 請求成功并且服務器未下發異常 51 * 52 * @param response 53 */ 54 protected abstract void onSuccess(T response); 55 56 /** 57 * 請求成功, 返回非繼承自BaseResponse的非標準Bean或字符串 58 * 59 * @param response 60 */ 61 protected void onOtherSuccess(T response) { 62 63 } 64 65 /** 66 * 請求成功,服務器下發異常 67 * 68 * @param response 69 */ 70 protected void onServiceError(T response) { 71 72 } 73 74 /** 75 * 網絡異常 76 * 77 * @param e 78 */ 79 protected void onNetError(Throwable e) { 80 if (mView != null && mView.get() != null) { 81 NetworkError.error(mView.get(), e); 82 } 83 } 84}放一張我畫的流程圖,比較魔性
三、使用示例
Contract
1public interface LoginContract {23 interface View extends BaseView {45 /**6 * 登陸成功7 * @param loginModel8 */9 void loginSuccess(LoginModel loginModel); 10 11 } 12 13 interface Presenter extends BasePresenter<View> { 14 15 /** 16 * 登陸 17 */ 18 void login(String userName, String pwd); 19 } 20} 21 22Activity 23 24public class LoginActivity extends BaseMvpActivity<LoginPresenter> implements LoginContract.View { 25 26 @BindView(R.id.et_login_user) 27 ClearEditText mEtLoginUser; 28 @BindView(R.id.et_login_password) 29 ClearEditText mEtLoginPassword; 30 31 @Override 32 protected int getLayout() { 33 return R.layout.activity_login; 34 } 35 36 @Override 37 protected void initEventAndData() { 38 initView(); 39 } 40 41 @Override 42 protected LoginPresenter createPresenter() { 43 return new LoginPresenter(); 44 } 45 46 private void initView() { 47 // ... 48 } 49 50 private void toLogin() { 51 mPresenter.login(mEtLoginUser.getText().toString(), mEtLoginPassword.getText().toString(); 52 } 53 54 @Override 55 public void loginSuccess(LoginModel loginModel) { 56 startActivity(new Intent(mContext, MainActivity.class)); 57 finish(); 58 } 59 60 @OnClick({R.id.tv_login_submit}) 61 public void onViewClicked(View view) { 62 switch (view.getId()) { 63 case R.id.tv_login_submit: 64 //上傳用戶名和密碼的方法 65 toLogin(); 66 break; 67 } 68 } 69 70}Presenter
1public class LoginPresenter extends SamplePresenter<LoginContract.View> implements LoginContract.Presenter {23 @Override4 public void login(String userName, String pwd) {5 RetrofitClient6 .getInstance()7 .gService8 .login()9 .compose(RxSchedulersUtils.rxObservableSchedulerHelper()) 10 .subscribe(new RetrofitSubscriber<BaseResponse<LoginModel>>(mView) { 11 @Override 12 protected void onSuccess(BaseResponse<LoginModel> response) { 13 mView.loginSuccess(response.getData()); 14 } 15 }); 16 } 17}三、源碼
https://github.com/sdwfqin/AndroidQuick/tree/2.x/app/src/main/java/com/sdwfqin/quickseed
總結
以上是生活随笔為你收集整理的mvp关联activity生命周期_Rxjava+Retrofit统一异常处理与生命周期管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql5.7审计功能开启_MySQL
- 下一篇: wps文字退格会删掉文字_WPS第二行文