Android当中的MVP模式封装之后的OkHttp工具在Model层

Posted 范二er

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android当中的MVP模式封装之后的OkHttp工具在Model层相关的知识,希望对你有一定的参考价值。

个人博客:CODE FRAMER BIGZ

MVP系列文章配套DEMO

Android 当中的 MVP 模式(一)基本概念


Android 当中的 MVP 模式(二)封装


Android 当中的 MVP 模式(三)基于分页列表的封装


Android 当中的 MVP 模式(四)插曲-封装 OkHttp


Android 当中的 MVP 模式(五)封装之后的 OkHttp 工具在 Model 层的使用


Android 当中的 MVP 模式(六)View 层 Activity 的基类— BaseMvpActivity 的封装


Android 当中的 MVP 模式(七)终篇—关于对 MVP 模式中代码臃肿问题的思考

摘要:在上一篇中对 OkHttp 进行了简单的封装,但是没有使用到这个系列当中的 Demo 里面,这一章就使用上一篇封装的 OkHttp 工具,替换掉之前 Demo 里面的 Model 层的网络请求.并且之前的部分接口方法都没有使用,比如说 IBasePresenter 接口中的 HashMap<String, String> getParams() 方法, IBasePaginationPresenter 中的 boolean hasMoreData() 方法,算是对上一篇的补充。

Model 层原来的写法

拿分页数据获取的 Model 层举例,当时在 SohuAlbumModel 中是这样获取数据的:


    @Override
    public void sendRequestToServer(Param param) 
        String validUrl = null;
        Log.d(TAG, ">> sendRequestToServer >> " + "has more data ?" + mPaginationPresenter.hasMoreData());
        if (param != null && !TextUtils.isEmpty(url) && mPaginationPresenter.hasMoreData()) 
            validUrl = getValidUrl(url, param);
            Log.d(TAG, ">> sendRequestToServer >> " + "ValidUrl:" + validUrl);
        

        if (!TextUtils.isEmpty(validUrl)) 
            HttpUtils.executeByGet(validUrl, new Callback() 
                @Override
                public void onFailure(Call call, IOException e) 
                    Log.d(TAG, ">> onFailure >> ");
                    e.printStackTrace();
                    mPaginationPresenter.okHttpError(Constants.URL_ERROR, e.getMessage(), url);
                

                @Override
                public void onResponse(Call call, Response response) throws IOException 
                    if (!response.isSuccessful()) 
                        Log.d(TAG, ">> onResponse >> " + "Not successful");
                        mPaginationPresenter.okHttpError(Constants.SERVER_ERROR, response.message(), url);
                    

                    String responseJson = response.body().string();
                    Log.d(TAG, ">> onResponse >> " + "responseJson:" + responseJson);
                    mPaginationPresenter.accessSuccess(responseJson);

                
            );
         else 
            Log.d(TAG, ">> sendRequestToServer >> " + "Valid Url is empty");
        
    

    private String getValidUrl(String url, Param param) 
        return String.format(url, param.getPageIndex(), param.getPageSize());
    

url 当中的参数是直接在 sendRequestToServer 方法中传递进来的,这么一来会让 Model 层的职责变得不那么单一,因为 Model 层只应该负责数据相关的工作,此处的 params 传递进来,还需要进行一个 url 的拼接工作,所以在这里是可以优化的地方。

在看看上一篇中的 OkHttpManager 类中请求服务器数据的核心方法:


    /**
     * 使用@link OkHttpClient想服务器端请求数据的方法
     * @param method @link Constants#HTTP_GET_METHOD Get方式,@link Constants#HTTP_POST_METHOD Post方式
     * @param baseUrl baseUrl
     * @param paramsMap 请求url的参数,以键值对的形式存放
     * @param handler
     */
    public void requestServerData(int method, String baseUrl, HashMap<String, String> paramsMap, DisposeDataHandler handler) 
        RequestParams requestParams = new RequestParams(paramsMap);
        Request request = null;
        if (method == Constants.HTTP_GET_METHOD) 
            request = CommonRequest.createGetRequest(baseUrl, requestParams);
         else if (method == Constants.HTTP_POST_METHOD) 
            request = CommonRequest.createPostRequest(baseUrl, requestParams);
        
        if (request != null) 
            mOkHttpClient.newCall(request).enqueue(new CommonJsonCallback(handler));
        

    

使用 OkHttpManager 来请求服务器获得数据,第二个参数 HashMap<String, String> paramsMap 就是已经在 Presenter 层中处理好的键值对参数,然后在 CommonRequest.createGetRequest(baseUrl, requestParams); 或者是 CommonRequest.createPostRequest(baseUrl, requestParams) 中就已经把完整的 url 拼接出来了。具体如何拼接,如何构造 Request 对象,Model 层完全不用关心,它只需要在请求成功或者是请求失败的回调接口中将数据回调到 Presenter 层去即可。

那么现在就开始重构 Model 层的方法。

Model 层现在的写法


    @Override
    public void sendRequestToServer() 
        if (mPaginationPresenter.hasMoreData()) 
            OkHttpManager.getInstance().requestServerData(method, baseUrl, mPaginationPresenter.getParams(), new DisposeDataHandler(new DisposeDataListener() 
                @Override
                public void onSuccess(Object responseObj) 
                    String responseJson = (String) responseObj;
                    Log.d(TAG, ">> onSuccess >> " + responseJson);
                    mPaginationPresenter.accessSuccess(responseJson);
                

                @Override
                public void onFailure(OkHttpException exception) 
                    Log.d(TAG, ">> onFailure >> " + exception.getErrorCode());
                    mPaginationPresenter.okHttpError(exception.getErrorCode(), exception.getErrorMsg(), url);
                
            , null));
        else 
            Log.d(TAG,">> sendRequestToServer >> " + "No more data!");
        
    

是不是简单了很多!和之前的方法相比较,有三处不同的地方:

  • 2 行的 sendRequestToServer() 方法中已经没有了 param 参数了。(那么参数从哪儿来呢?)
  • 3 行多了一个 hasMoreData() 的方法,用于判断服务器端还有没有更多的数据。若没有,那就没有必要去请求了。它是在哪儿初始化的?
  • 4 行的多了 mPaginationPresenter.getParams() ,它是在什么地方初始化的?
  • 4 行的 baseurl 不是之前 Model 层的 url

下面就解释为什么可以这么操作。

BasePaginationPresenter 的修改

观察之前 Model 层的写法就知道,这个地方的参数,主要是从其中取出 pageIndexpageSize ,用于拼接新的 url ,然后再请求数据,这儿不需要这个参数了, 那肯定就是有地方已经提供了这个参数了咯。 对,就是 mPaginationPresenter.getParams() 这个之前没有用过的方法,先回顾一下这个方法在哪儿定义的:


    public interface IBasePresenter<Param> 
        //省略部分代码
        /**
         * 在Model层中调用,此方法用于获取Presenter层处理好的参数
         * @author zfy
         * @return 请求参数
         * @Created at 2017/10/21/021 15:05
         */
        HashMap<String, String> getParams();
    

第二篇中,针对每一层封装的时候,这个接口就已经定义好了,只是一直没有使用上,在这儿就用上了。而 BasePaginationPresenter 类是实现这个街口的,并且这个 Presenter 是分页请求数据中 Presenter 层的基类,在第三篇也提到过。下面看看 BasePaginationPresenter


    /**
     * @author:ZengFanyu
     * @date:2017/10/20
     */
    public abstract class BasePaginationPresenter<Param extends BasePaginationParam, Data> implements IBasePaginationPresenter<Param> 

        //省略部分代码

        /**
         * 子类实现,用于确认服务器端是否还有数据
         *
         * @return true-还有数据 false-没有数据
         */
        public abstract boolean serverHaveMoreData();

        /**
         * 子类实现,用于返回请求服务器的url当中的参数
         *
         * @return HashMap<String,String> url 中的 kay value 对
         */
        public abstract HashMap<String, String> getHttpRequestParams();

        //省略部分代码

        @Override
        public HashMap<String, String> getParams() 
            return getHttpRequestParams();
        

        @Override
        public boolean hasMoreData() 
            return serverHaveMoreData();
        
    

只贴出和之前不同的部分,

  • 多了一个 serverHaveMoreData() 抽象方法,子类去实现的,用于判断服务器还有没有更多的数据。
  • 多了以个 getHttpRequestParams() 抽象方法,子类去实现,用于将参数填充到 HashMap 中,供 Model 层使用。

接下里看看子类 AlbumPresenter 的实现:

AlbumPresenter 的修改


    /**
     * @author:ZengFanyu
     * Function:
     */
    public class AlbumPresenter extends BasePaginationPresenter<BasePaginationParam, Album> 
        private int mTotalCount=-1;

        public AlbumPresenter(BaseMvpActivity baseListView, Class<Album> aClass) 
            super(baseListView, aClass);
            this.mBaseListView = baseListView;
            getModel().setRequestMethod(Constants.HTTP_GET_METHOD);
            getModel().setRequestUrl(Constants.SOHU_SERIALS_URL_BASE);
        

        //省略代码

        @Override
        public void serverResponse(Album album) 

            //省略代码

            mTotalCount = album.getData().getCount();

        

        @Override
        public boolean serverHaveMoreData() 
            //此处pageIndex是从1开始的, 实际适用需要注意pageIndex的起始值
            int pageSize = mParam.getPageSize();
            int pageIndex = mParam.getPageIndex();
            //第一次需要返回true 才能进到 serverResponse 方法中去初始化 mTotalCount 值
            return mTotalCount == -1 || (pageIndex * pageSize) <= mTotalCount;
        

        @Override
        public HashMap<String, String> getHttpRequestParams() 
            HashMap<String, String> paramsMap = new HashMap<>();
            paramsMap.put("cid", "2");
            paramsMap.put("o", "1");
            paramsMap.put("plat", "6");
            paramsMap.put("poid", "1");
            paramsMap.put("api_key", "9854b2afa779e1a6bff1962447a09dbd");
            paramsMap.put("sver", "6.2.0");
            paramsMap.put("sysver", "4.4.2");
            paramsMap.put("partner", "47");
            paramsMap.put("page", String.valueOf(mParam.getPageIndex()));
            paramsMap.put("page_size", String.valueOf(mParam.getPageSize()));
            return paramsMap;
        

    

与之前实现不同地方在于:

  • 构造方法当中设置的 url ,现在是 baseUrl ,后面的参数由 getHttpRequestParams方法生成,在CommonRequest 中生成完整 url
  • serverResponse() 方法中,对 mTotalCount 进行了初始化, 这个值就是记录服务器端一共有多少条数据的。
  • serverHaveMoreData()拿当前已经加载的数据条数和 mTotalCount 进行对比,判断是否还有数据。
  • getHttpRequestParams() 构造参数的 HashMap

小结

从这一章的从重构部分代码,很明显可以看到,各层之间的依赖关系:

  • 主要是替换网络请求的工具,那么就是只涉及到 Model 层的改动。
  • 这里 Presenter 层改动了,其实是不需要改动的, 这里改动了的原因是,我把之前没有实现的功能补上了,并且将sendRequestToServer() 的参数去掉了导致的。
  • 可以发现, View 层代码没有进行一点修改,也就是 Activity 并没有动。

个人博客地址 :CODER FRAMER BIGZ

以上是关于Android当中的MVP模式封装之后的OkHttp工具在Model层的主要内容,如果未能解决你的问题,请参考以下文章

Android 当中的 MVP 模式封装

Android当中的MVP模式插曲-封装OkHttp

Android当中的MVP模式插曲-封装OkHttp

Android当中的MVP模式基于分页列表的封装

Android当中的MVP模式View 层 Activity 的基类--- BaseMvpActivity 的封装

Android当中的MVP模式View 层 Activity 的基类--- BaseMvpActivity 的封装