Android-Retrofit2+Rxjava2之网络通用请求-初步封装-完善优化数据【对象】请求

上一篇我们进行了初步封装的总结,同时针对分页列表的请求做了简单的调用请求处理。这篇我们接着调用BaseControlPresenter的requestData方法获取数据【对象】 - 非列表的方式。

1. 创建服务

    private BaseControlContract.Presenter presenter;
    ///< 创建请求服务
    presenter = new BaseControlPresenter(this, new BaseControlPresenter.DataHandler() {
            @Override
            public String String2Data(String strData) {
                return strData;
            }
        });

2. 发起请求

 ///< 获取钱包地址
 presenter.requestData("eth-addr", null);

 ///< 领取糖果
 HashMap paramsList = new HashMap<>();
 paramsList.put("id", candyId + "");
 paramsList.put("eth_address", walletAddr.getText().toString().trim());
 presenter.requestData("receive-candy-detail", paramsList);

3. 成功回调

    @Override
    public  void onSucess(T t) {
        String str = (String) t;
        if (str.contains("eth_address")) {
            CandyBean.ethAddr ethAddr = JSON.parseObject(str, new TypeReference() {
            });
            walletAddr.setText(ethAddr.getEth_address());
        } else if (str.contains("content") || str.contains("msg")) {
            CandyBean.ethSuccess ethSuccess = JSON.parseObject(str, new TypeReference() {
            });
            walletAddr.setVisibility(View.GONE);
            receiveRoot.setVisibility(View.VISIBLE);
            successTip.setText(ethSuccess.getMsg());
            invationokWv.loadDataWithBaseURL(null, ethSuccess.getContent(), "text/html", "utf-8", null);
        }
    }

分析一下:

1. 解析返回还是String return strData;

2. 请求参数为null?

3. onSucess(T t)中进行Json处理?

为什么这个感觉有点麻烦,1. 一方面没有提前做Json解析,2. 而且我们之前的方法貌似传null有问题,但是确实这个请求方法没有参数。3. 另外onSuccess中根据返回字符串分别进行了解析,貌似有点麻烦,而且位置也不好,提前处理就好了!

解决:问题2我们修改下我们之前的请求方法的部分代码requestData(...)

image

问题1和问题3 (目前这样没有问题,但是我还是想把数据解析提前做,放到io线程中进行处理)。为什么onSuccess中我们进行了分别处理,因为这个页面有多个网络请求,而我们的通用请求只有一个回调,再多搞回调感觉也没必要。

但是如果只创建一个服务的情况下,数据解析返回的类型最多只能定义一个:

image

这样另外一个对象就没办法作为泛型类型了,如下

image

那小白就想,有没有好点的方式,小白想了下,针对目前的页面来讲:

1. 可以只定义实体类,把两个网络请求json的字段全部包含,然后进行转换;使用时判断某个字段是否为空,进而区分应该取哪些字段。

2. 另外一种就是返回类型修改为Object, 然后onSuccess中instanceof判断是哪个对象类型,进而获取数据进行显示。

拿第二种来看:

      ///< 创建请求服务
        presenter = new BaseControlPresenter(this, new BaseControlPresenter.DataHandler() {
            @Override
            public Object String2Data(String strData) {
                if (strData.contains("eth_address")) {
                    CandyBean.ethAddr ethAddr = JSON.parseObject(strData, new TypeReference() {
                    });
                    return ethAddr;
                } else if (strData.contains("content") || strData.contains("msg")) {
                    CandyBean.ethSuccess ethSuccess = JSON.parseObject(strData, new TypeReference() {
                    });
                    return ethSuccess;
                }
                return null;
            }
        });

回调时:

    @Override
    public  void onSucess(T t) {
        if (t instanceof CandyBean.ethAddr){
            CandyBean.ethAddr ethAddr = (CandyBean.ethAddr) t;
            walletAddr.setText(ethAddr.getEth_address());
        }else if (t instanceof CandyBean.ethSuccess){
            CandyBean.ethSuccess ethSuccess = (CandyBean.ethSuccess) t;
            walletAddr.setVisibility(View.GONE);
            receiveRoot.setVisibility(View.VISIBLE);
            successTip.setText(ethSuccess.getMsg());
            invationokWv.loadDataWithBaseURL(null, ethSuccess.getContent(), "text/html", "utf-8", null);
        }
    }

再拿第一种来看:

完善实体类

CandyBean.java

@NotProguard
public class CandyBean {
    /**
     * eth_address : 0xCAb8eEA4799a21379c20eF5Bba2CC8bF1bEC475B
     */

    private String eth_address;
    /**
     * content : 

1

* msg : 领取成功!共领取3.95个test */ private String content; private String msg; public CandyBean(){} public String getEth_address() { return eth_address; } public void setEth_address(String eth_address) { this.eth_address = eth_address; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } @NotProguard public static class ethAddr{ /** * eth_address : 0xCAb8eEA4799a21379c20eF5Bba2CC8bF1bEC475B */ private String eth_address; public ethAddr(){} public String getEth_address() { return eth_address; } public void setEth_address(String eth_address) { this.eth_address = eth_address; } } @NotProguard public static class ethSuccess{ /** * content :

1

* msg : 领取成功!共领取3.95个test */ private String content; private String msg; public ethSuccess(){} public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } } }

请求json解析

   ///< 创建请求服务
        presenter = new BaseControlPresenter(this, new BaseControlPresenter.DataHandler() {
            @Override
            public CandyBean String2Data(String strData) {
                return  JSON.parseObject(strData, new TypeReference() {});
            }
        });

然后回调处理

   @Override
    public  void onSucess(T t) {
        CandyBean candyBean = (CandyBean) t;
        if (null != candyBean.getEth_address() && !candyBean.getEth_address().contains("")){
            walletAddr.setText(candyBean.getEth_address());
        }else{
            walletAddr.setVisibility(View.GONE);
            receiveRoot.setVisibility(View.VISIBLE);
            successTip.setText(candyBean.getMsg());
            invationokWv.loadDataWithBaseURL(null, candyBean.getContent(), "text/html", "utf-8", null);
        }
    }

讲真的,从上面看还是第一种方式代码量,什么的要简洁些,而且也不必要定义另外两个对象。当然这只是这种情况,有些请求数据差异特别大的,而且关联性不强的,没有必要搞一个实体类了,那样混合起来不好看!

小白想,其实还有一种方式,就是请求的时候传入JSON解析处理回调,那里给泛型类型,就能解析返回想要的类型(不用去做类型区分啥的):

   /**
         * 请求数据【对象】
         * @param _funUrl
         * @param _paramList
         */
        void requestDataSB(final String _funUrl, HashMap _paramList, BaseControlPresenter.DataHandler _dataHandler);

请求

presenter.requestDataSB("eth-addr", null, new BaseControlPresenter.DataHandler() {
            @Override
            public CandyBean.ethAddr String2Data(String strData) {
                return JSON.parseObject(strData, new TypeReference() {});
            }
        });

回调的地方判断下属于哪个类型对象就可以进行强转处理了...

或许还有更好的方案,希望可以赐教!

小白还想考虑把这个请求的url能不能统一管理? 同时转换的地方能不能也做个统一管理?请求url统一管理很有必要,毕竟之后可能要升级,要修改啥的!

统一管理url,小白想这样搞:搞一个管理类,然后通过静态hashmap进行存储,存储的key则是请求的实体类类类型, value就是方法字符串

NetUrlManager.java

import com.x.finance.bean.CandyBean;

import java.util.HashMap;

public class NetUrlManager {
    private static HashMap classStringHashMap = new HashMap() {
        {
            put(CandyBean.ethAddr.class, "eth-addr");
            put(CandyBean.ethSuccess.class, "receive-candy-detail");
        }
    };

    public static String getFunUrl(Class _class) {
        return classStringHashMap.get(_class);
    }
}

然后在requestData调用传递的方法字符串修改为传递实体类类类型

   ///< 获取钱包地址
   presenter.requestData(CandyBean.ethAddr.class, null);

   ///< 领取糖果
   HashMap paramsList = new HashMap<>();
   paramsList.put("id", candyId + "");
   paramsList.put("eth_address", walletAddr.getText().toString().trim());
   presenter.requestData(CandyBean.ethSuccess.class, paramsList);

然后requestData里面处理下

image

这样就统一做了下处理。不然字符串方法作为参数很难管理和维护。

小白又想?既然实体类的Class类型都作为参数传入了,那么同样我们解析是不是也可以通过类似的管理方式进行统一管理?getBean

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.x.finance.bean.CandyBean;

import java.util.HashMap;

/*
*@Description: 方法url管理+类型转换管理
*@Author: hl
*@Time: 2018/11/22 16:18
*/
public class NetUrlManager {
    private static HashMap classStringHashMap = new HashMap() {
        {
            put(CandyBean.ethAddr.class, "eth-addr");
            put(CandyBean.ethSuccess.class, "receive-candy-detail");
        }
    };

    private static HashMap classClassHashMap = new HashMap() {
        {
            put(CandyBean.ethAddr.class, CandyBean.ethAddr.class);
            put(CandyBean.ethSuccess.class,  CandyBean.ethSuccess.class);
        }
    };

    public static String getFunUrl(Class _class) {
        return classStringHashMap.get(_class);
    }

    public static Object getBean(String strData, Class _class) {
        if (_class.getName().equals(CandyBean.ethAddr.class.getName())){
            return JSON.parseObject(strData, new TypeReference() {});
        }else if (_class.getName().equals(CandyBean.ethSuccess.class.getName())){
            return JSON.parseObject(strData, new TypeReference() {});
        }
        return null;
    }
}

然后BaseControlPresenter里面盗用下

image

这样下来,我们的视图里面创建服务时的回调就不用传了....(记得把构造函数private修改为public)

image

省去了很多麻烦,也方便管理维护。。不过我们的每个请求就需要对应一个对象(其实小白认为这也可以,每个请求一个对象也没啥,也方便管理)。另外回调的地方也判断下类型进行处理:

    @Override
    public  void onSucess(T t) {
        if (t instanceof CandyBean.ethAddr){
            CandyBean.ethAddr ethAddr = (CandyBean.ethAddr) t;
            walletAddr.setText(ethAddr.getEth_address());
        }else if (t instanceof CandyBean.ethSuccess){
            CandyBean.ethSuccess ethSuccess = (CandyBean.ethSuccess) t;
            walletAddr.setVisibility(View.GONE);
            receiveRoot.setVisibility(View.VISIBLE);
            successTip.setText(ethSuccess.getMsg());
            invationokWv.loadDataWithBaseURL(null, ethSuccess.getContent(), "text/html", "utf-8", null);
        }
    }

其实也还好,总得来说还是节省了代码,易用性也增加了。

行吧,初步封装可能就先到这里了。还有别的学习任务需要尽快跟上。小白体会到了设计模式,泛型,接口等需要综合熟练的使用才能搞出好的封装。看了泛型,json解析这块还得加深原理的性的东西才行! - 最后列表请求的方式也可以这样优化下哈.....自己搞搞就好了...sb,sb,sb, sb, 酷酷滴....

如果有好的建议,希望能教教小白,感谢! Next, let's hold on......

你可能感兴趣的:(Android-Retrofit2+Rxjava2之网络通用请求-初步封装-完善优化数据【对象】请求)