上一篇我们进行了初步封装的总结,同时针对分页列表的请求做了简单的调用请求处理。这篇我们接着调用BaseControlPresenter的requestData方法获取数据【对象】 - 非列表的方式。
1. 创建服务
private BaseControlContract.Presenter presenter;
///< 创建请求服务
presenter = new BaseControlPresenter<String>(this, new BaseControlPresenter.DataHandler<String>() {
@Override
public String String2Data(String strData) {
return strData;
}
});
2. 发起请求
///< 获取钱包地址
presenter.requestData("eth-addr", null);
///< 领取糖果
HashMap<String, String> paramsList = new HashMap<>();
paramsList.put("id", candyId + "");
paramsList.put("eth_address", walletAddr.getText().toString().trim());
presenter.requestData("receive-candy-detail", paramsList);
3. 成功回调
@Override
public <T> void onSucess(T t) {
String str = (String) t;
if (str.contains("eth_address")) {
CandyBean.ethAddr ethAddr = JSON.parseObject(str, new TypeReference<CandyBean.ethAddr>() {
});
walletAddr.setText(ethAddr.getEth_address());
} else if (str.contains("content") || str.contains("msg")) {
CandyBean.ethSuccess ethSuccess = JSON.parseObject(str, new TypeReference<CandyBean.ethSuccess>() {
});
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(...)
问题1和问题3 (目前这样没有问题,但是我还是想把数据解析提前做,放到io线程中进行处理)。为什么onSuccess中我们进行了分别处理,因为这个页面有多个网络请求,而我们的通用请求只有一个回调,再多搞回调感觉也没必要。
但是如果只创建一个服务的情况下,数据解析返回的类型最多只能定义一个:
这样另外一个对象就没办法作为泛型类型了,如下
那小白就想,有没有好点的方式,小白想了下,针对目前的页面来讲:
1. 可以只定义实体类,把两个网络请求json的字段全部包含,然后进行转换;使用时判断某个字段是否为空,进而区分应该取哪些字段。
2. 另外一种就是返回类型修改为Object, 然后onSuccess中instanceof判断是哪个对象类型,进而获取数据进行显示。
拿第二种来看:
///< 创建请求服务
presenter = new BaseControlPresenter<Object>(this, new BaseControlPresenter.DataHandler<Object>() {
@Override
public Object String2Data(String strData) {
if (strData.contains("eth_address")) {
CandyBean.ethAddr ethAddr = JSON.parseObject(strData, new TypeReference<CandyBean.ethAddr>() {
});
return ethAddr;
} else if (strData.contains("content") || strData.contains("msg")) {
CandyBean.ethSuccess ethSuccess = JSON.parseObject(strData, new TypeReference<CandyBean.ethSuccess>() {
});
return ethSuccess;
}
return null;
}
});
回调时:
@Override
public <T> 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);
}
}
再拿第一种来看:
完善实体类
@NotProguard
public class CandyBean {
/**
* eth_address : 0xCAb8eEA4799a21379c20eF5Bba2CC8bF1bEC475B
*/
private String eth_address;
/**
* content : <p>1</p>
* 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 : <p>1</p>
* 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<CandyBean>(this, new BaseControlPresenter.DataHandler<CandyBean>() {
@Override
public CandyBean String2Data(String strData) {
return JSON.parseObject(strData, new TypeReference<CandyBean>() {});
}
});
然后回调处理
@Override
public <T> 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
*/
<T>void requestDataSB(final String _funUrl, HashMap<String, String> _paramList, BaseControlPresenter.DataHandler<T> _dataHandler);
请求
presenter.<CandyBean.ethAddr>requestDataSB("eth-addr", null, new BaseControlPresenter.DataHandler<CandyBean.ethAddr>() {
@Override
public CandyBean.ethAddr String2Data(String strData) {
return JSON.parseObject(strData, new TypeReference<CandyBean.ethAddr>() {});
}
});
回调的地方判断下属于哪个类型对象就可以进行强转处理了...
或许还有更好的方案,希望可以赐教!
小白还想考虑把这个请求的url能不能统一管理? 同时转换的地方能不能也做个统一管理?请求url统一管理很有必要,毕竟之后可能要升级,要修改啥的!
统一管理url,小白想这样搞:搞一个管理类,然后通过静态hashmap进行存储,存储的key则是请求的实体类类类型, value就是方法字符串
import com.x.finance.bean.CandyBean;
import java.util.HashMap;
public class NetUrlManager {
private static HashMap<Class, String> classStringHashMap = new HashMap<Class, String>() {
{
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<String, String> paramsList = new HashMap<>();
paramsList.put("id", candyId + "");
paramsList.put("eth_address", walletAddr.getText().toString().trim());
presenter.requestData(CandyBean.ethSuccess.class, paramsList);
然后requestData里面处理下
这样就统一做了下处理。不然字符串方法作为参数很难管理和维护。
小白又想?既然实体类的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<Class, String> classStringHashMap = new HashMap<Class, String>() {
{
put(CandyBean.ethAddr.class, "eth-addr");
put(CandyBean.ethSuccess.class, "receive-candy-detail");
}
};
private static HashMap<Class, Class> classClassHashMap = new HashMap<Class, Class>() {
{
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<CandyBean.ethAddr>() {});
}else if (_class.getName().equals(CandyBean.ethSuccess.class.getName())){
return JSON.parseObject(strData, new TypeReference<CandyBean.ethSuccess>() {});
}
return null;
}
}
然后BaseControlPresenter里面盗用下
这样下来,我们的视图里面创建服务时的回调就不用传了....(记得把构造函数private修改为public)
省去了很多麻烦,也方便管理维护。。不过我们的每个请求就需要对应一个对象(其实小白认为这也可以,每个请求一个对象也没啥,也方便管理)。另外回调的地方也判断下类型进行处理:
@Override
public <T> 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......