一时兴起的MVP+RxJava+Retrofit的封装录
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介绍:
Retrofit 其实相当简单,简单到源码只有37个文件,其中22个文件是注解还都和HTTP有关,真正暴露给用户的类并不多,所以我看了一遍 官方教程 大多数情景就可以无障碍使用,如果你还没有看过,可以先去看看,虽然是英文,但代码才是最好的教程不是么?当然本篇文章会介绍得详细一点,不能写一篇水文,毕竟我给它命名为《你真的会用Retrofit2吗?Retrofit2完全教程》。附上链接https://www.jianshu.com/p/308f3c54abdd。 进入正题吧,我们首先来尝试搭建一个MVP框架: 1、从View开始,新建一个BaseView接口,定义一下View层通用的方法;
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能自行实现自己的需求;
public interface LoginView extends BaseView {void loginSuccess(); void loginFailure(); }
【一时兴起的MVP+RxJava+Retrofit的封装录】OK,我们现在有了登录模块的View了,那么,我们可以在相关登录模块的Activitiy,Fragment上实现该LoginView,例如:
public class LoginActivity extends BaseActivityimplements LoginView{ @Override public void loginSuccess() { } @Override public void loginFailure() { } }
好的,那么我们的LoginActivity就实现了我们的LoginView功能了,BaseActivity待会会介绍;
View大概就这么多,可以根据具体的功能需求添加删除;
2、Presenter层:由上文提到的,负责逻辑处理;
同样,新建一个BasePresenter类,因为presenter层级的操作是基于View层的,我们需要在BasePresenter每一步操作前判断我们的view是否存在;
public class BasePresenter{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{/** * 登录方法 */ 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
3、来看看BaseActivity,直接上代码:
public abstract class BaseActivityextends 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 BaseActivityimplements 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) {} }
4、上面似乎还少了个Model层,Model层主要是负责数据,如网络访问,数据库查询等操作,该层没有进一步进行封装了,先来看看Presenter层里是怎样跟Model层交互的;
public class LoginPresenterImpl extends LoginPresenter {@Override public void login(String phoneNum, String password) { if (isViewAttached()) { Map params = new HashMap<>(); params.put("phoneNum", phoneNum); params.put("password", password); UserModel.login(getContext(), params, new Callback() { @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 params, Callbackcallback) { RetrofitManager.getInstance().createService(UserApi.class).login(params) .compose(RetrofitManager.getInstance().ioMainSchedulers()) .subscribe(new BaseObserver<>(context, callback)); } }
LoginResponse是服务端返回的实体数据,具体如何造就看你服务端具体返回什么了;
Callback是一个通用的接口,如下:
public interface Callback{/** * 数据请求成功 * * @param data */ void onSuccess(T data); /** * 使用网络API接口请求方式时,虽然已经请求成功但是由 * 于{@code msg}的原因无法正常返回数据。 */ void onFailure(int errCode, String msg); }
5、终于到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(); }publicT createService(Class clazz) { return retrofit.create(clazz); }public ObservableTransformer ioMainSchedulers() { return upstream -> upstream.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()); } }
主要就是实现一个单例模式,然后配合RxJava进行使用,如下login接口:
public interface UserApi {@FormUrlEncoded @POST(HttpConstants.LOGIN) Observable> login(@FieldMap Map params); }
Retrofit+RxJava主要是接口返回参数为RxJava的Observable,就是这么简单,深入的我也还没去研究,先用起来吧。
Ok,大概就是这样了。这样的话,我们的各层级进行了应有的解耦,代码也干净了很多。但是,代码量我觉得是多了的。
自己随手记录的一些内容,相当于是复习了下RxJava,Retrofit的使用和Mvp的概念,不喜勿喷。
转载于:https://www.cnblogs.com/Jhon-Mr/p/9628828.html
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量