Mvp烫止、RxJava炸客、Retrofit疾棵、Dagger這些當前流行的框架相信大家都聽說過,這里不對這些做科普痹仙,這里主要分享一下個人的框架搭建是尔,希望對大家的學習有所幫助。
漢之風云
項目地址: https://github.com/hanzhifengyun/Mvp_RxJava_Retrofit_Dagger
Mvp
/**
* Presenter基類
*/
public interface BasePresenter<T extends BaseView>{
void attachView(T view);
void detachView();
void onStart();
}
/**
* View基類
*/
public interface BaseView {
/**
* 顯示網(wǎng)絡不可用
*/
void showNetWorkError();
/**
* 顯示錯誤信息
*
* @param message
*/
void showErrorMessage(String message);
/**
* 顯示加載彈框
*/
void showLoadingDialog(boolean cancelable);
/**
* 隱藏加載彈框
*/
void hideLoadingDialog();
/**
* 退出該界面
*/
void finishActivity();
}
這里用登錄頁面舉例:
/**
* 登錄契約
*/
public interface LoginContract {
interface View extends BaseView {
/**
* 設置用戶名
*
* @param userName 用戶名
*/
void setUserName(String userName);
/**
* 設置密碼
*
* @param password 用戶名
*/
void setPassword(String password);
/**
* 設置刪除用戶名按鈕可見
*/
void showClearUserNameButton();
/**
* 設置刪除用戶名按鈕不可見
*/
void hideClearUserNameButton();
/**
* 設置用戶名為空
*/
void setUserNameEmpty();
/**
* 設置密碼明文
*/
void showPassword();
/**
* 設置密碼密文
*/
void hidePassword();
/**
* 顯示用戶名不能為空
*/
void showUserNameEmpty();
/**
* 跳轉(zhuǎn)HomeActivity
*/
void openHomePage();
}
interface Presenter extends BasePresenter<View> {
/**
* 當輸入框用戶名改變
*
* @param userName 用戶名
*/
void onEdtUserNameChanged(String userName);
/**
* 當刪除用戶名按鈕被點擊
*/
void onBtnClearUserNameClick();
/**
* 當顯示隱藏密碼按鈕被點擊
*
* @param needShow 是否需要顯示
*/
void onBtnShowOrHidePasswordClick(boolean needShow);
/**
* 當?shù)卿洶粹o被點擊
* @param user 用戶信息
*/
void login(User user);
}
}
通過登錄頁面這里講一下我對Mvp的理解:
- View層只處理Presenter交代的UI交互开仰,同時傳遞用戶對UI操作信息給到Presenter去處理對應邏輯拟枚。
- Presenter接收View層傳遞過來的用戶操作,根據(jù)業(yè)務邏輯直接調(diào)用View層UI展示众弓,或者通過Model層講本地或者遠程處理后的數(shù)據(jù)傳遞給View層展示恩溅。
- Model層負責處理本地或者遠程數(shù)據(jù),只被Presenter層調(diào)用谓娃,不直接與View層接觸脚乡。
RxJava
首先封裝一層Presenter:View在BaseRxJavaPresenter中被綁定
/**
* 便于管理所有Presenter的Disposable
*/
public abstract class BaseRxJavaPresenter<T extends BaseView> implements BasePresenter<T> {
protected T mView;
protected CompositeDisposable mCompositeDisposable = new CompositeDisposable();
protected void addDisposable(Disposable disposable) {
if (mCompositeDisposable == null) {
mCompositeDisposable = new CompositeDisposable();
}
mCompositeDisposable.add(disposable);
}
protected void dispose() {
if (mCompositeDisposable != null) {
mCompositeDisposable.clear();
}
}
@Override
public void attachView(T view) {
mView = view;
}
@Override
public void detachView() {
this.mView = null;
dispose();
}
}
還是以登陸Presenter為例:
/**
* 登錄
*/
public class LoginPresenter extends BaseRxJavaPresenter<LoginContract.View> implements LoginContract.Presenter {
private LoginRepository mLoginRepository;
private ISchedulerProvider mSchedulerProvider;
@Inject
public LoginPresenter(@NonNull LoginRepository loginRepository,
@NonNull ISchedulerProvider schedulerProvider) {
mLoginRepository = checkNotNull(loginRepository, "loginRepository cannot be null");
mSchedulerProvider = checkNotNull(schedulerProvider, "schedulerProvider cannot be null");
}
@Override
public void onStart() {
mLoginRepository.getUser()
.subscribeOn(mSchedulerProvider.io())
.observeOn(mSchedulerProvider.ui())
.subscribe(new OnceObserver<User>() {
@Override
protected void onResponse(User value) {
mView.setUserName(value.getName());
}
});
}
@Override
public void login(User user) {
//驗證用戶名不能為空
if (user.isUserNameEmpty()) {
mView.showUserNameEmpty();
return;
}
mLoginRepository.loginRemote(user)
.subscribeOn(mSchedulerProvider.io())
.doOnNext(new Consumer<User>() {
@Override
public void accept(User value) throws Exception {
//子線程保存用戶數(shù)據(jù)
value.setLogin(true);
mLoginRepository.saveUser(value);
}
})
.observeOn(mSchedulerProvider.ui())
.subscribe(new OnceLoadingObserver<User>(mView) {
@Override
protected void onResponse(User value) {
//UI操作UI線程
mView.openHomePage();
mView.finishActivity();
}
});
}
......其他實現(xiàn)
}
這里我封裝了兩個一次性的觀察者:
- OnceObserver:調(diào)用完后立即解除觀察
- OnceLoadingObserver(BaseView baseView, boolean cancelable):需在主線程調(diào)用并回調(diào)在主線程,封裝調(diào)用是彈出加載框滨达,cancelable決定加載框是否能取消每窖,對調(diào)用錯誤結(jié)果統(tǒng)一處理,baseView提示網(wǎng)絡錯誤弦悉、接口錯誤等信息窒典。調(diào)用完后關閉加載框,立即解除觀察稽莉。
對于切換線程這里用到了ISchedulerProvider瀑志,是個接口:
public interface ISchedulerProvider {
/**
* @return 計算線程
*/
@NonNull
Scheduler computation();
/**
* @return 可復用的子線程
*/
@NonNull
Scheduler io();
/**
* @return Android主線程
*/
@NonNull
Scheduler ui();
/**
* @return 新的子線程
*/
@NonNull
Scheduler newThread();
}
這里貼一下實現(xiàn)類:
@Singleton
public class SchedulerProvider implements ISchedulerProvider {
@Inject
public SchedulerProvider() {
}
@Override
@NonNull
public Scheduler computation() {
return Schedulers.computation();
}
@Override
@NonNull
public Scheduler io() {
return Schedulers.io();
}
@Override
@NonNull
public Scheduler newThread() {
return Schedulers.newThread();
}
@Override
@NonNull
public Scheduler ui() {
return AndroidSchedulers.mainThread();
}
}
用過Dagger的人從注解可以看出是已單例的方式依賴注入的。
Dagger
@Module
public class UtilModule {
@Provides
@Singleton
ISchedulerProvider provideSchedulerProvider(SchedulerProvider schedulerProvider) {
return schedulerProvider;
}
@Provides
@Singleton
IJsonHandler provideJsonHandler(GsonHandler gsonHandler) {
return gsonHandler;
}
}
UtilModule在單例的ApplicationComponent中被依賴:
@Singleton // Constraints this component to one-per-application or unscoped bindings.
@Component(modules = {ApplicationModule.class,
HttpModule.class, UtilModule.class,
UserModule.class})
public interface ApplicationComponent {
void inject(AndroidApplication application);
/**
* @return 上下文
*/
Context getContext();
/**
* @return 線程調(diào)度器
*/
ISchedulerProvider getSchedulerProvider();
LoginRepository getLoginRepository();
IJsonHandler getJsonHandler();
}
Retrofit
public interface LoginRemoteService {
/**
* 登錄
*/
@POST(IRestApi.URL_API_POST)//替換真實接口后綴
Observable<BaseModel<User>> loginRemote(@Body RequestBody requestBody);
/**
* 退出
*/
@POST(IRestApi.URL_API_POST)
Observable<BaseModel<Object>> logoutRemote(@Body RequestBody requestBody);
}
通過Dagger實例化
@Module
public class HttpModule {
private final String baseUrl;
private final boolean isDebug;
public HttpModule(String baseUrl, boolean isDebug) {
this.baseUrl = baseUrl;
this.isDebug = isDebug;
}
@Provides
@Singleton
OkHttpClient provideOkHttpClient(Context context) {
return OkHttpFactory.create(context, isDebug);
}
@Provides
@ResultType //表示直接返回對象類型
@Singleton
Retrofit provideResultRetrofit(OkHttpClient okHttpClient) {
return RetrofitFactory.createGsonWithRxJavaRetrofit(baseUrl, okHttpClient);
}
@Provides
@StringType //表示返回Json String類型
@Singleton
Retrofit provideStringRetrofit(OkHttpClient okHttpClient) {
return RetrofitFactory.createStringWithRxJavaRetrofit(baseUrl, okHttpClient);
}
}
然后在UserModule中依賴
@Module
public class UserModule {
@Provides
@Singleton
LoginRemoteService provideLoginRemoteService(@ResultType Retrofit retrofit) {
//這里引用了ResultType的Retrofit實例
return retrofit.create(LoginRemoteService.class);
}
@Singleton
@Provides
ILoginLocalApi provideLoginLocalApi(LoginLocalApi loginLocalApi) {
return loginLocalApi;
}
@Singleton
@Provides
ILoginRemoteApi provideLoginRemoteApi(LoginRemoteApi loginRemoteApi) {
return loginRemoteApi;
}
}
框架的代碼量比較多污秆,這里只貼出部分關鍵的接口及依賴劈猪, 具體實現(xiàn)感興趣的可以查看源碼,希望對大家的學習有所幫助良拼。
項目地址: https://github.com/hanzhifengyun/Mvp_RxJava_Retrofit_Dagger