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 {
/**
* 显示网络不可用
*/
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();
/**
* 跳转HomeActivity
*/
void openHomePage();
}
interface Presenter extends BasePresenter<View> {
/**
* 当输入框用户名改变
*
* @param userName 用户名
*/
void onEdtUserNameChanged(String userName);
/**
* 当删除用户名按钮被点击
*/
void onBtnClearUserNameClick();
/**
* 当显示隐藏密码按钮被点击
*
* @param needShow 是否需要显示
*/
void onBtnShowOrHidePasswordClick(boolean needShow);
/**
* 当登录按钮被点击
* @param user 用户信息
*/
void login(User user);
}
}
通过登录页面这里讲一下我对Mvp的理解:
- View层只处理Presenter交代的UI交互,同时传递用户对UI操作信息给到Presenter去处理对应逻辑。
- Presenter接收View层传递过来的用户操作,根据业务逻辑直接调用View层UI展示,或者通过Model层讲本地或者远程处理后的数据传递给View层展示。
- Model层负责处理本地或者远程数据,只被Presenter层调用,不直接与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 {
//子线程保存用户数据
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();
}
});
}
......其他实现
}
这里我封装了两个一次性的观察者:
- OnceObserver:调用完后立即解除观察
- OnceLoadingObserver(BaseView baseView, boolean cancelable):需在主线程调用并回调在主线程,封装调用是弹出加载框,cancelable决定加载框是否能取消,对调用错误结果统一处理,baseView提示网络错误、接口错误等信息。调用完后关闭加载框,立即解除观察。
对于切换线程这里用到了ISchedulerProvider,是个接口:
public interface ISchedulerProvider {
/**
* @return 计算线程
*/
@NonNull
Scheduler computation();
/**
* @return 可复用的子线程
*/
@NonNull
Scheduler io();
/**
* @return Android主线程
*/
@NonNull
Scheduler ui();
/**
* @return 新的子线程
*/
@NonNull
Scheduler newThread();
}
这里贴一下实现类:
@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 线程调度器
*/
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;
}
}
框架的代码量比较多,这里只贴出部分关键的接口及依赖, 具体实现感兴趣的可以查看源码,希望对大家的学习有所帮助。
项目地址: https://github.com/hanzhifengyun/Mvp_RxJava_Retrofit_Dagger