Android管道式MVP结合Retrofit

前言:

现在很多项目,或市面上80%的程序员都存在以下特点:

你写的代码像首诗,我写的代码像坨屎。
你写的代码是艺术,我写的代码是对付。
你的代码体现了高超的技术,我的代码出现了超多的事故。

所以,今天在新项目中封装retrofit,打算做出诗意般的代码,好好封装一下,敲出一手优美的诗。

但是结局却是个打油诗。

而且隔几个小时再看的时候,尼玛这是YY喊麦。

正文:

MVP设计模式,结合Retrofit,在网上找了好多,各种各样,都不是我心中所想的那样,有的甚至只有VP层,把M层当成了一个Bean。呵呵。

我认为M层应该是数据源的获取,而且可以分担部分的Presenter层的负担。令Presenter层代码不冗余。

抽象:

M层中BaseModle,我的demo很简单,可根据实际项目扩展:

/**
 */

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:

/**
 * 处理类超类
 * 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:

/**
 */

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:

/**
 */

public interface ILoginView extends IBaseView {
    @Override
    void onDataSuccess(Object o, int requestCode);

    @Override
    void onDataError(Object o, int requestCode);
}

View层可以根据具体需要再多定制自己的方法。现在本demo中,只有数据加载成功和失败的回调。

P层的LoginPresenter:

/**
 * 登陆处理类
 */

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工具类:

/**
 */

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业务类:

/**
 * 网络请求类
 */

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

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值