将retrofit2集成到同时具有webservice和http请求的Android项目中的解决方案
来源:互联网 发布:linux cp怎么用 编辑:程序博客网 时间:2024/05/23 05:08
retrofit2集成(webService、http)
适用环境
1、项目中既有webService服务,也有http服务;
2、项目原有服务是webService或者http其中的一种,由于需求变更等原因要更换服务类型,同时要在不影响原来的服务请求的情况下进行网络框架重构;
3、写服务的换人了;<或者服务人员想装逼,彰显他会多种服务语言>
retrofit2简单介绍
retrofit是由Square公司出品的针对于Android和Java的类型安全的Http客户端。简单的说就是一种网络请求框架,对okHttp的封装,使用面向接口的方式进行网络请求,利用动态生成的代理类封装了网络接口请求的底层,其将请求返回javaBean,对网络认证 REST API进行了很好对支持此,使用Retrofit将会极大的提高我们应用的网络体验。
【其实自己是看了github上的网络框架使用统计,排名第一的就是retrofit,所以就去稍稍的研究了一下,发现还挺好用,毕竟这热度可不是水军给刷上去的。】
下面就以我自己的项目中的例子来给大家演示一下今天的核心内容:
实例讲解
一、情景重现
为了迎合后台服务人员(以前公司的后台只会写webService)的服务类型,我们移动端选择采用比较常用ksoap网络请求框架来请求webService服务,首先以图片的形式看一下项目中ksoap网络请求的封装类。
以上就是原来项目中用到的ksoap网络请求帮助类,看起来也还OK,但是在实际的项目中,每到一次网络请求就要new出来一个handler或者asyncTask去处理网络请求,并且代码写起来很长很冗余,导致一个页面有多个请求的时候,光关于网络请求的代码就一大堆。另外原来的项目也灭有框架可言,基本大部分的代码都在activity或者fragment中,导致界面工作效率过低,代码过于混乱。
【这里有个不大不小的坑,注意图片中红色部分,留着到后面再讲QAQ】
基于这样的情况,项目组经过商议后决定要重构项目,其中就包括网络请求框架。要求在不改变以前程序代码的基础下进行代码重构。所以经过慎重考虑后,决定将retrofit2集成进我们的项目中去。
二、retrofit集成
1、首先导入retrofit2的相关依赖:
//retrofit网络框架 compile 'com.squareup.retrofit2:retrofit:2.3.0' //retrofit2.3.0类库 compile'com.squareup.retrofit2:converter-scalars:2.3.0' //关于字符串的转换器 compile 'com.squareup.retrofit2:converter-gson:2.3.0' //关于gson的转换器 compile 'com.squareup.okhttp3:logging-interceptor:3.4.1' //okhttpClient的log拦截器
2、http请求:
依赖包导入成功后就可以放肆的利用retrofit2进行实验了,首先用一个简单的http请求测试一下是否能走通。
public interface PostApi { /** * 上传错误信息接口 * */ @POST("api/OPERATION_ERROR_STATISTICS") Call<ResponseBody> postError(@Body ErrorBean bean); }
以上是一个简单的post请求接口。
【实体类就不贴了,自定义任何一个实体类都可以】
然后是请求的方法及回调:
public void errorPost(List<CrashBean> list){ //创建retrofit Retrofit retrofit = new Retrofit.Builder() .baseUrl(ActionNet.BASE_URL) .client(getOkHttpClient()) .addConverterFactory(GsonConverterFactory.create()) .build(); PostApi api = retrofit.create(PostApi.class); ErrorBean bean = new ErrorBean(); bean.setData(list); Call<ResponseBody> call = api.postError(bean); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { try { if(response.body() != null){ String result = response.body().string(); Log.e(TAG+"Error", "onResponse: "+result); } } catch (IOException e) { e.printStackTrace(); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { Log.e(TAG+"Error", "onFailure: "); } }); }
retrofit2的具体实现我就不说了,相信大家都已经了解过retrofit2了。
程序走了一遍可以走通,证明了retrofit2是可以正常使用的。
3、retrofit2请求webService
好了,轮到本文重头戏上场了。
首先,尝试着使用retrofit2请求webService:
【当然对于这个刚开始我是一脸懵逼的,要不是网上有一些关于retrofit2请求webService的文章,我还真的不知道从何下手,毕竟webService的请求接口中注解有点儿复杂】
/**
* 获取补丁版本
* */
@Headers({“Content-Type: text/xml;charset=UTF-8”, “SOAPAction: http://tempuri.org/getNewAppPatch“}) //请求的Action,类似于方法名
@POST(“GetTJWebService.asmx”)
Call getNewAppPatch(@Body String envelope);
看到webService请求接口里的请求头了吧,超复杂的感觉。【注意我的请求实体类是String,使用String是为了所有的请求都能公用一个类,所以就把实体类转换成String并进行封装(当然simplexml的转换器可以自动将实体类进行解析,但是这样太麻烦,每一个请求都要写一大堆转换类)】
首先要知道webService服务是以xml的形式进行请求并返回数据,这里给大家贴一下webService的请求
可以看到,webService的请求和返回都是有固定格式的要求(这里用的是soap1.1版本),所以这里为了使所有的webService请求都能适配,我这里封装了一个自定义的请求及返回数据的处理类,即webService的请求和接收都是将参数或者返回数据处理成String字符串进行请求和接收。代码如下:
public class Node { public static String toStart(String name){ return "<"+name+"@gt;"; } public static String toEnd(String name){ return "</"+name+">"; } public static String getRequest(String namespace, Map<String,String> map){ StringBuffer sbf = new StringBuffer(); String startStr = "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +" <soap:Body>\n" +" <"+namespace+" xmlns=\"http://tempuri.org/\">\n"; sbf.append(startStr); for (Map.Entry<String,String> entry : map.entrySet()){ sbf.append(" <"+entry.getKey()+">"+entry.getValue()+"</"+entry.getKey()+">\n"); } String endStr = " </"+namespace+">\n" +" </soap:Body>\n" +"</soap:Envelope>"; sbf.append(endStr); return sbf.toString(); }}
这是请求的封装,下面是接收的封装:
public Map<String,String> dealResponse(Response<ResponseBody> response){ Map<String,String> map = new HashMap<>(); String head = response.raw().request().header("SOAPAction"); String url = response.raw().request().url().toString(); String type = null,data = null,res = null; try { if(head != null){ //webService请求 String name = head.replace(AppNet.NAME_SPACE, ""); type = url+"/"+name; data = response.body().string().replaceAll("<","<").replaceAll(">",">"); res = StringUtils.substringBetween(data,"<"+name+"Result>","</"+name+"Result>"); }else { //Http请求 type = url; data = response.body().string(); res = data; } } catch (IOException e) { e.printStackTrace(); } map.put("data",res); map.put("url",type); return map; }
这样请求和接收的转换都有了,现在就来测试一下请求webService。
请求接口上面已经贴过了,下一步就是创建retrofit,这里我进行了一下封装。
//创建retrofitpublic void creatRetrofit(){ if(retrofit == null){ OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder(); HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient client = okHttpClient.connectTimeout(2, TimeUnit.MINUTES) .writeTimeout(2, TimeUnit.MINUTES) .readTimeout(2, TimeUnit.MINUTES) .addInterceptor(httpLoggingInterceptor) .build(); retrofit = new Retrofit.Builder() .baseUrl(this.BASE_URL) .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .client(client) .build(); } if(mService == null){ mService = retrofit.create(UserService.class); }}
【注意:ScalarsConverterFactory一定要加上,不然无法将String字符串转换成xml的请求格式,这个坑我可是看了好久才搞出来,一定要注意细节!】
其中UserService是我的接口类。
然后就是发出请求:
public void getVerson(String xml, Callback<ResponseBody> callback){ Call<ResponseBody> call = mService.getNewAppPatch(xml); call.enqueue(callback);}
请求之后是回调:
@Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { if(response.body() != null){ map = model.dealResponse(response); data = map.get("data"); url = map.get("url"); if(model.isWebService(response)){ //进行xml解析 switch (url){ case "": break; } }else { //进行json解析 switch (url){ case "": break; } } }else { Log.e("fail", "requestFailed"); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { Log.e("error", "requestError"); }
【这里的回调和上面的返回数据转换,我把webService和http都进行了区分,这样不管是webService还是http都可以公用一个回调,适用于一个页面既有webService也有http请求,并且都是多个请求。】
本以为这样就可以万事大吉,但是点一下运行,程序报错了,我们来看看报错内容吧:
一目了然,依赖包冲突,而且是OkHttp3的依赖包冲突。心想,我的项目里没有导入OkHttp啊,哪来的冲突?于是乎我就在项目中进行寻找,还真让我找到了:
原来如此,ksoap的jar包里包含了okhttp3,而且retrofit是强制封装了OkHttp3,所以才会有冲突,这样的话就只好去重了啊,我的方法是这样的,把ksoap包里的okhttp3和okio这两个包给删掉,然后我们在文章顶部中soapUtils类里,把红色部分改为HttpTransportSE就可以了。
然后再运行,项目完完整整的跑出来了。这就是将retrofit2集成到同时具有webService和http请求的项目中去的解决方案了。
总结
1、把webService的请求和接收封装起来,这样使请求更加方便。
2、在retrofit2请求webService的时候,如果要使用String转换的话一定要加上ScalarsConverterFactory的转换器;
3、ksoap的jar包里是有okhttp请求的,所以retrofit和ksoap会有冲突依赖,根据实际情况解除冲突;
4、本文没有具体的说明retrofit请求http和webService的教程,如果大家不是很了解,建议去看看其他博主的博客,如:
http://blog.csdn.net/lmj623565791/article/details/51304204 retrofit2完全解析
http://www.jianshu.com/p/b865c855a1e8 retrofit2 + OkHttp + WebService请求
5、建议你的后台人员只写一种服务,因为这样的多种请求真是要搞死人QAQ。
本博主第一次写这么长的文章,希望大家多多支持,有什么不对的还希望大家多多指正。
代码还没来得及上传到github,如有需要请留言。
谢谢侬!(鞠躬)
- 将retrofit2集成到同时具有webservice和http请求的Android项目中的解决方案
- android 5.0之后原生webview同时用https请求不了http的资源图片解决方案
- 将jax-ws webservice集成到web项目中
- 将retrofit2和rxjava的初始化配置到application
- 关于XMPPFramework的简介和集成到项目中的问题解决
- Retrofit2的get请求和post请求
- Retrofit2的get请求和post请求
- 如何将项目同时托管到 Git@OSC 和 Github
- 如何将项目同时托管到 Git@OSC 和 GitHub
- 将项目同时托管到Github和Git@OSC
- Webservice 用http get方式无法请求到的解决办法
- 将其他Android项目打成aar包集成到自己的项目中
- jax-ws开发的webservice集成到web项目中
- Retrofit2.0在android项目中的使用
- Android 使用Retrofit2.0 + OKHttp 实现 HTTP协议请求
- 将Android源码集成到Eclipse中的方法
- webservice和http请求的 客户端调用代码
- PJSIP集成到Android项目的历程
- CentOS下安装Redis
- SpringMVC与Ajax(Json,String,Form)数据交互
- http协议
- LeetCode
- MobileNet教程:用TensorFlow搭建在手机上运行的图像分类器
- 将retrofit2集成到同时具有webservice和http请求的Android项目中的解决方案
- Nginx--官网中文翻译(中英文对比)--5-调试日志A debugging log
- 服务器显卡驱动安装NVIDIA-1080Ti
- dubbo管理控制台安装和使用
- linux(6)
- SEO(搜索引擎优化)浅谈网站站内链接优化的一些策略
- cassandra cql查询
- Python爬虫利器之Beautiful Soup的用法
- Why Did the Cow Cross the Road III