Android管道式MVP结合Retrofit
来源:互联网 发布:电子处方单软件 编辑:程序博客网 时间:2024/06/14 10:12
前言:
现在很多项目,或市面上80%的程序员都存在以下特点:
你写的代码像首诗,我写的代码像坨屎。
你写的代码是艺术,我写的代码是对付。
你的代码体现了高超的技术,我的代码出现了超多的事故。
所以,今天在新项目中封装retrofit,打算做出诗意般的代码,好好封装一下,敲出一手优美的诗。
但是结局却是个打油诗。
而且隔几个小时再看的时候,尼玛这是YY喊麦。
正文:
MVP设计模式,结合Retrofit,在网上找了好多,各种各样,都不是我心中所想的那样,有的甚至只有VP层,把M层当成了一个Bean。呵呵。
我认为M层应该是数据源的获取,而且可以分担部分的Presenter层的负担。令Presenter层代码不冗余。
抽象:
M层中BaseModle,我的demo很简单,可根据实际项目扩展:
/** * Created by WenCheeseXu on 2017/12/14. */public abstract class IBaseModle { public abstract void setListener(IBasePrecenter.IBaseDataListener listener);}
抽象的M层,由于当前项目需求不明确,所以只有一个为当前Modle设置监听。这个监听的接口定义在Precenter的抽象中,因为是P层要调M层,所以这个接口定义就定义在这里的话,给人感觉比较直观。
View层的IBaseView:
public abstract interface IBaseView { public abstract void onDataSuccess(Object o, int requestCode); public abstract void onDataError(Object o, int requestCode);}
抽象出了两个方法,分别是加载成功的回调,和加载失败的回调,这些回调中去操作UI。MV层解耦初步展现,操作UI和业务逻辑与数据加载分开定义。
P层的IBasePrecenter:
/** * Created by WenCheeseXu on 2017/12/14. * 处理类超类 * T 请求类型 * E 错误返回类型,一般是String,返回错误信息 * J 请求返回类型 * Y 中间件返回类型 */public abstract class IBasePrecenter { public interface IBaseDataListener<T extends Object, E extends Object, J extends Object, Y extends Object> { //中间本地处理 public Y onPipeline(T request, J response); //成功回调 public void onDataSuccess(Y o, int requestCode); //错误回调 public void onDataError(E o, int requestCode); } //构造方法调用初始化 public IBasePrecenter() { initPrecenter(); } public abstract void initPrecenter();}
P层的抽象中,定义了一个接口,用于P层中调用M层的时候与M层解耦,效果不好。
这个接口使用泛型,支持中间管道式数据处理,用于自己定制自己的逻辑。
在获取到数据之后的处理,写在这个中间的管道方法中。
此抽象有待完善,现估应该抽象出next()方法,适配更多种情况。同时,抽象出更多的next重载方法,加强管道的数据处理能力。比如说,单个数据如何处理,多个数据如何处理,不想处理时,直接调用next的空参数方法,进行对应的listener回调。
抽象层设计完毕,接下来是实现类们。
实现:
M层的LoginModle:
/** * Created by WenCheeseXu on 2017/12/15. */public class LoginModle extends IBaseModle { //管道回调 private IBasePrecenter.IBaseDataListener listener; //请求路径 private String path = "/sb/login.json"; //设置管道回调 @Override public void setListener(IBasePrecenter.IBaseDataListener listener) { this.listener = listener; } //调用RetrofitService进行网络请求 public void doLogin(UserBean o, final int req) { RetrofitService.getRetrofitService() .doPost(o, req, path, listener); }}
主要设置了管道listener,然后调用Retrofit封装好的方法,进行网络请求。Retrofit的具体封装,在下面会有。
参数中UserBean o就是请求实体,int req是请求码,在页面通过请求码来判断对应的请求。
View层的ILoginView:
/** * Created by WenCheeseXu on 2017/12/15. */public interface ILoginView extends IBaseView { @Override void onDataSuccess(Object o, int requestCode); @Override void onDataError(Object o, int requestCode);}
View层可以根据具体需要再多定制自己的方法。现在本demo中,只有数据加载成功和失败的回调。
P层的LoginPresenter:
/** * Created by WenCheeseXu on 2017/12/15. * 登陆处理类 */public class LoginPrecenter extends IBasePrecenter { //MVP Modle private LoginModle modle; //管道回调 private IBaseDataListener<UserBean, String, UserBean, UserBean> listener; //MVP View private IBaseView view; //构造方法接收View层 public LoginPrecenter(IBaseView view) { this.view = view; } //调用M层进行逻辑处理 public void doLogin(UserBean o, int requestCode) { modle.doLogin(o, requestCode); } /** * 初始化控制器Presenter层 * 包括: * 1、 初始化Modle层 * 2、 实现管道回调逻辑 */ @Override public void initPrecenter() { modle = new LoginModle(); listener = new IBaseDataListener<UserBean, String, UserBean, UserBean>() { /** * 管道中间处理逻辑 * @param request 请求Bean 泛型中第一个类 * @param response 返回Bean 泛型中第三个类 * @return 将request与Response处理过的Bean 泛型中第四个类 */ @Override public UserBean onPipeline(UserBean request, UserBean response) { /* 进行中间处理...... */ return response; } /** * 成功回调 * @param o 处理后的Bean 泛型中第三个类 * @param requestCode 请求码 */ @Override public void onDataSuccess(UserBean o, int requestCode) { /* 回调View层,进行UI操作 */ view.onDataSuccess(o, requestCode); } /** * 失败回调 * @param o 失败信息 泛型中第二个类 * @param requestCode 请求码 */ @Override public void onDataError(String o, int requestCode) { /* 回调View层,进行UI处理 */ view.onDataError(o, requestCode); } }; //将管道回调怼进M层 modle.setListener(listener); }}
P层主要做的事有:
1、获取到V层(构造方法中)。
2、获取到M层(initPrecenter方法中)。
3、利用管道回调接口,将M与P关联。
4、调用M层处理业务,处理结果中调用V层操作UI,解耦M层V层。
5、可以在管道中对结果进行拦截,修改,处理定制任务再分发。
至此MVP解耦,并对加载数据进行拦截操作,规范又优雅的实现了定制任务。
目前只是完成了对管道接口的实现,自己定制的业务直接写在onPipeline方法中,规范了代码,后期完善过后,将会出现更强大的功能。(写到这里,发现和RxJava2.+的管道有些像,我仿佛封装了一个RxJava)。
可以发现P层中的管道监听接口的实现,是不是有些像AsyncTask?只要在声明的时候,写好三个对应的泛型,在AS中,就会自动实现,效率贼高。
Retrofit工具类:
/** * Created by WenCheeseXu on 2017/12/18. */public class RetrofitUtil { public static Retrofit retrofit; public static String BASE_URL = ServerParams.getBaseUrl(); //创建获取retrofit实例 public static Retrofit buildRetrofit() { if (retrofit == null) { synchronized (RetrofitUtil.class) { if (retrofit == null) { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); } } } return retrofit; } /** * 通用post方法。 */ public interface RetrofitPost { @POST("{path}") Call<Object> retrofitPost(@Body Object t, @Path("path") String path); } /** * 通用post方法 * * @param <T> */ public interface RetrofitGet<T> { @GET("{path}") Call<T> retrofitGet(@Path("path") String path); }}
此工具类,单例模式。通用的post方法之前也是利用泛型设计,但是利用泛型会在调用Retrofit源码的,返回Call< T >的create方法出错。于是post的方法封装没有用泛型,而是直接利用“万物皆Object大法”。
Retrofit业务类:
/** * Created by WenCheeseXu on 2017/12/18. * 网络请求类 */public class RetrofitService { /** * 单例模式 */ private RetrofitService() { } private static RetrofitService retrofitService; /** * 单例模式获取Service * * @return this */ public static RetrofitService getRetrofitService() { if (retrofitService == null) { synchronized (RetrofitService.class) { retrofitService = new RetrofitService(); } } return retrofitService; } /** * 公用POST方法 * * @param o Post的请求实体 * @param requestCode 请求码 * @param path 请求路径 * @param listener 请求的控制器,用于回调 */ public void doPost(final Object o, final int requestCode, String path, final IBasePrecenter.IBaseDataListener listener) { RetrofitUtil .buildRetrofit() .create(RetrofitUtil.RetrofitPost.class) .retrofitPost(o, path) .enqueue(new Callback<Object>() { @Override public void onResponse(Call<Object> call, Response<Object> response) { Object piped;//经处理过的中间件 if (response.isSuccessful()) {//请求成功,返回码大于等于200小于300 //中间处理 piped = listener.onPipeline(o, response.body()); if (piped != null) //处理过 listener.onDataSuccess(piped, requestCode); else listener.onDataError("管道处理失败", requestCode); } else listener.onDataError(response.code(), requestCode); } @Override public void onFailure(Call<Object> call, Throwable t) { listener.onDataError("请求失败", requestCode); } }); } /** * 通用GET方法 * * @param o GET的实体类,一般没有 * @param requestCode 请求码 * @param path 请求路径 * @param listener 回调控制器 */ public void doGet(Object o, final int requestCode, String path, final IBasePrecenter.IBaseDataListener listener) { RetrofitUtil.buildRetrofit() .create(RetrofitUtil.RetrofitGet.class) .retrofitGet(path) .enqueue(new Callback<Object>() { @Override public void onResponse(Call<Object> call, Response<Object> response) { if (response.isSuccessful()) listener.onDataSuccess(response.body(), requestCode); else listener.onDataError(response.code(), requestCode); } @Override public void onFailure(Call<Object> call, Throwable t) { listener.onDataError("请求失败", requestCode); } }); }}
Service层,单例模式获取。由于之前的封装结合Retrofit,在这里的公用Post方法中可以进行链式操作。
其中:
RetrofitUtil .buildRetrofit()返回Retrofit实例
.create(RetrofitUtil.RetrofitPost.class) 返回一个Call< RetrofitPost >
.retrofitPost(o, path) 回一个Call< Object >。
这里对管道的方法进行了调用,管道方法继续完善过后,可以自定义一些强大的方法,YY请参考RxJava。
LoginActivity中,简单介绍下:
首先应该实现View层接口:
public class LoginActivity extends BaseFragmentActivity implements ILoginView {
其次获取一个P层实例:
private LoginPrecenter precenter; //中间相隔若干行代码 precenter = new LoginPrecenter(this);
实现View层回调,我这里只写了一个,登陆失败的回调:
@Override public void onDataSuccess(Object o, int requestCode) { } @Override public void onDataError(Object o, int requestCode) { Intent intent = new Intent(); intent.putExtra(Param.LOGIN_RESULT,Param.LOGIN_CACEL); setResult(RESULT_CANCELED,intent); finish(); }
最后,通过P层去跑逻辑:
//登录 loginBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { userName = inputNameEt.getText().toString().trim(); password = inputPwdEt.getText().toString().trim(); userBean.setUserName(userName); userBean.setUserPwd(password); precenter.doLogin(userBean, DOLOGIN); } });
至此,一个封装好的管道式MVP设计模式的Retrofit网络加载框架就封装完毕。
调用起来非常简单:
1、定义Modle继承自IBaseModle。
2、Modle中调用封装好的retrofit加载网络。
3、定义Presenter继承自IBasePresenter。
4、管道中定制自己需要的方法,数据加载成功失败回调View层。
5、实现View层。
PS:在Modle层中,可以不用公用doPost方法,自己定义特殊的,符合情景的Post方法。
明天上传GitHub。太晚了,睡觉。
- Android管道式MVP结合Retrofit
- 浅谈Android MVP设计模式(简单结合RxJava+Retrofit)
- 【android进阶篇】MVP+Retrofit+RxJava框架结合
- MVP架构下Android的Rxjava与Retrofit 结合
- Android Mvp设计模式结合RxJava+OkHttp+retrofit浅谈
- Android——MVP+xRecyclerView+Retrofit+OkHttp+RxJava结合应用
- Android MVP +Retrofit+RxJava
- MVP封装成基类结合retrofit和Rxjava
- MVP封装成基类结合retrofit和Rxjava
- MVP+Retrofit+RxJava(Flowable)结合使用
- Android Mvp+Rxjava+Retrofit实战
- Android Mvp+RxJava+Retrofit 实战
- Android Retrofit+RxJava+MVP封装
- Android mvp+Retrofit 登录注册
- MVP+ Retrofit+RxJava+XRecyclerView+TabLayout+Fresco结合使用
- MVP和Retrofit+Rxjava+OkHttp封装结合请求数据
- MVP结合RecycleView,利用retrofit与RxJava简单请求数据
- MVP + Retrofit
- 为什么要使用回调函数
- EasyNVR NVR网页无插件直播在兼容宇视NVR RTSP流媒体时PLAY过程对Scale的兼容
- 通过微信分享链接,后面被加上from=singlemessage&isappinstalled=1导致网页打不开
- FAQ(16):Parameter 'userRole' not found. Available parameters are [UserRole, param1]
- CSDN如何获取下载分以及进入下载频道必须知道的规则
- Android管道式MVP结合Retrofit
- Vue 简单介绍和指令
- 升级到新版的 vue-cli 的两个问题
- GNU Radio ieee802-15-4、ZigBee 实现
- 交换机(五)其它层级的交换技术
- 6.Curator测试以及常用场景的实现
- cxf 之 Hello World Web Service
- 笔记:udacity计算机科学导论- 课程11/14-17数组append,+,len的谜题
- 简介C和C++语言历史