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。太晚了,睡觉。

阅读全文
1 0
原创粉丝点击