Retrofit 最简单的快速入门及自己封装
2017-01-10 23:22
381 查看
简单介绍及官方文档的坑
官方文档 http://square.github.io/retrofit/Retrofit是Square公司开发的一款针对Android网络请求的框架,Retrofit2底层基于OkHttp实现的,OkHttp现在已经得到Google官方认可,大量的app都采用OkHttp做网络请求
Retrofit也就成了最火的网络请求框架之一,想着来研究一下Retrofit了…先看了看官方文档,发现各种坑,Retrofit是结合着注解来做的,思路新颖,但是不符合大部分开发程序员的思维习惯,一开始使用的时候,不太适应…附上官方文档的介绍
Retrofit turns your HTTP API into a Java interface. public interface GitHubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); } The Retrofit class generates an implementation of the GitHubService interface. Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .build(); GitHubService service = retrofit.create(GitHubService.class); Each Call from the created GitHubService can make a synchronous or asynchronous HTTP request to the remote webserver. Call<List<Repo>> repos = service.listRepos("octocat");
快速入门,从Hello 百度走起
想快速入门Retrofit,我们最简单的想法是能请求一下www.baidu.com,然后将信息打印一下,但是发现在Retrofit入门的时候,访问www.baidu.com竟然成了奢求…,大部分的文章都是模仿着官方文档来写的…先一起来写一个访问百度,展示数据的示例
第一步:gradle文件中进行配置
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta2' compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta2' compile 'com.squareup.retrofit2:converter-scalars:2.0.0'
第二步:定义一个接口,接口中使用注解注明请求方式,及对应的请求路径
public interface DataService { //指定get请求方式 指定路径 有时候路径除了baseUrl还有一部分比如 http://write.blog.csdn.net/mdeditor //http://write.blog.csdn.net/ 一般是baseUrl //而 mdeditor是相对路径的 @GET Call<String> baidu(@Url String url); }
第二步:进行请求
//创建Retrofit对象 Retrofit retrofit = new Retrofit.Builder() //指定baseurl,这里有坑,最后后缀出带着“/” .baseUrl("http://www.baidu.com/") //设置内容格式,这种对应的数据返回值是String类型 .addConverterFactory(ScalarsConverterFactory.create()) //定义client类型 .client(new OkHttpClient()) //创建 .build(); //通过retrofit和定义的有网络访问方法的接口关联 DataService dataService = retrofit.create(DataService.class); //在这里又重新设定了一下baidu的地址,是因为Retrofit要求传入具体,如果是决定路径的话,路径会将baseUrl覆盖掉 Call<String> baidu = dataService.baidu("http://wwww.baidu.com"); //执行异步请求 baidu.enqueue(new Callback<String>() { @Override public void onResponse(Call<String> call, Response<String> response) { Toast.makeText(MainActivity.this, response.body(), Toast.LENGTH_SHORT).show(); } @Override public void onFailure(Call<String> call, Throwable t) { } });
通过上述代码,咱们就可以完整的看见百度的html界面了,算是对Retrofit做一个入门
其他请求-QQ吉凶测试
第三方网站聚合数据上的测试地址,key有可能过期,大家测的时候可以自己申请key 官网 https://www.juhe.cnhttp://japi.juhe.cn/qqevaluate/qq?key=96efc220a4196fafdfade0c9d1e897ac&qq=295424589
返回数据内容
{"error_code":0,"reason":"success","result":{"data":{"conclusion":"[大吉+官运+财运+才艺]如龙得云,青云直上,智谋奋进,才略奏功","analysis":"欲望难足希望高,计谋成功财力豪,猜疑嫉妒性自改,如龙乘云势运开。智能超人贯彻大志,富贵无比,不甘寂寞,叱吒风云之大吉数,但容易发生牢骚及贪心、欲望太多而永不知足,为其缺点。切忌沉迷投机,可免贻误前程。"}}}
对于Retrofit可以直接生成对应的json
第一步:生成对应的Bean,例如 QQData
第二步:在接口中定义请求方法
GET请求
请求相对路径
参数内容
Call代表是一个请求
public interface DataService { @GET("/qqevaluate/qq") Call<QQData> getQQData(@Query("key") String appkey, @Query("qq") String qq); }
第三步:开始请求
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://japi.juhe.cn") .addConverterFactory(GsonConverterFactory.create()).build(); DataService dataService = retrofit.create(DataService.class); final Call<QQData> qqData = dataService.getQQData("96efc220a4196fafdfade0c9d1e897ac", "11111111"); qqData.enqueue(new Callback<QQData>() { @Override public void onResponse(Response<QQData> response, Retrofit retrofit) { String reason = response.body().getReason(); Toast.makeText(MainActivity.this, response.body().getReason(), Toast.LENGTH_SHORT).show(); } @Override public void onFailure(Throwable t) { Toast.makeText(MainActivity.this, "--" + t.getMessage().toString(), Toast.LENGTH_SHORT).show(); } });
以上是Retrofit的简单应用,当然对于Retrofit还有一些其他的方式
///https://zhidao.baidu.com/daily/view //路径拼接的形式,v代表是其中的一个参数,可以在这个位置进行拼接 @GET("daily/{v}") Call<String> baiduzhidao(@Path("v") String v); //在注解中指定路径,定义相对应的参数的集合 @GET("qqevaluate/qq") Call<QQData> getQQDataMap(@QueryMap Map<String,String> map); //对应Post请求,参数的注解是@Field @POST("qqevaluate/qq") Call<QQData> postQQData(@Field("key") String key,@Field("qq") String qq); //必须指定进行表单编码 @FormUrlEncoded //指定参数是map形式 @FieldMap @POST("qqevaluate/qq") Call<QQData> postQQDataMap(@FieldMap Map<String,String> map);
自己封装一个简易的Retrofit请求
对于Retrofit,我们发现确实有一些特色,请求也比较简单,但是,当在一个大的项目中,不可能每一请求都到接口中声明一下。所以有必要进行简易的封装封装一个简易的请求接口
public interface ProjectAPI { //http://www.baidu.com/aaa?key=123&qq=aaa @GET Call<String> getMethod(@Url String url); @FormUrlEncoded @POST Call<String> postMethod(@Url String url, @FieldMap Map<String,String> map); }
定义一个网络请求的管理类,需要注意的是这里的baseUrl创建了,如果url是在其基础上的,就会进行相应的拼接,如果url是全路径,就会覆盖掉baseUrl
public class HttpManger { /** * @param baseUrl 基础Url * @param url 附加Url * @param callback 添加请求回调,这里直接使用的是Retrofit自身的回调接口 */ public static void getMethod(String baseUrl, String url, final Callback<String> callback) { Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl).addConverterFactory(ScalarsConverterFactory.create()).build(); ProjectAPI projectAPI = retrofit.create(ProjectAPI.class); Call<String> call = projectAPI.getMethod(url); call.enqueue(new Callback<String>() { @Override public void onResponse(Call<String> call, Response<String> response) { //调用回调 callback.onResponse(call, response); } @Override public void onFailure(Call<String> call, Throwable t) { //调用回调 callback.onFailure(call, t); } }); }
Post请求方式的封装,参数通过map集合的方式进行传递
public static void postMethod(String baseUrl, String url, Map<String, String> map, final Callback<String> callback) { //指定客户端 Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl).client(httpClient).addConverterFactory(ScalarsConverterFactory.create()).build(); ProjectAPI projectAPI = retrofit.create(ProjectAPI.class); Call<String> call = projectAPI.postMethod(url, map); call.enqueue(new Callback<String>() { @Override public void onResponse(Call<String> call, Response<String> response) { callback.onResponse(call, response); } @Override public void onFailure(Call<String> call, Throwable t) { callback.onFailure(call, t); } }); }
方法调用-Get方式调用,这里的key大家可以替换一下
HttpManger.getMethod("http://japi.juhe.cn/", "http://japi.juhe.cn/qqevaluate/qq?key=96efc220a4196fafdfade0c9d1e897ac&qq=295424589", new Callback<String>() { @Override public void onResponse(Call<String> call, Response<String> response) { Toast.makeText(MainActivity.this, "--"+response.body(), Toast.LENGTH_SHORT).show(); } @Override public void onFailure(Call<String> call, Throwable t) { Toast.makeText(MainActivity.this, "--"+t.getMessage(), Toast.LENGTH_SHORT).show(); } });
POST方式调用
Map<String, String> map=new HashMap<>(); map.put("key","96efc220a4196fafdfade0c9d1e897ac"); map.put("qq","111111111"); HttpManger.postMethod(false,false,"http://japi.juhe.cn/","qqevaluate/qq",map,new Callback<String>(){ @Override public void onResponse(Call<String> call, Response<String> response) { Toast.makeText(MainActivity.this, "--"+response.body(), Toast.LENGTH_SHORT).show(); } @Override public void onFailure(Call<String> call, Throwable t) { Toast.makeText(MainActivity.this, "--"+t.getMessage(), Toast.LENGTH_SHORT).show(); } });
正好最近做到了Cookie的应用,在本讲解中进行一下讲解
创建一个保存Cookie的拦截器,用于获取服务器打给客户端的Cookie信息
public class SaveCookiesInterceptor implements Interceptor { @Override public okhttp3.Response intercept(Chain chain) throws IOException { //获取到响应 Response originalResponse = chain.proceed(chain.request()); //进行Cookie获取以及字符串的拼接,Cookie在使用的过程要 //根据具体公司来定 if (!originalResponse.headers("Set-Cookie").isEmpty()) { //根据Set-Cookie获取出的信息 for (String header : originalResponse.headers("Set-Cookie")) { Log.i("AAAA----","=="+header+"=="); String cookie = header.substring(0, header.indexOf(";") + 1); stringBuilder.append(cookie); } } //拼接时完成后将该Cookie保存到 SharedPreferences中 SharedPreferencesUtils.saveString(MyApplication.context,"cookie",stringBuilder.toString()); return originalResponse; } }
创建读取Cookie的拦截器
public class ReadCookiesInterceptor implements Interceptor { @Override public okhttp3.Response intercept(Chain chain) throws IOException { Request.Builder builder = chain.request().newBuilder(); String cookie = SharedPreferencesUtils.getString(MyApplication.context, "cookie", ""); //将cookie添加到请求头中 builder.addHeader("Cookie", cookie); return chain.proceed(builder.build()); } }
在HttpManager中指定拦截器的使用,但是并不是所有的请求都要保存cookie或者所有的请求都要读取cookie,所以我们添加一个判断
/** * * @param isReadCookie 是否要读取cookie * @param isSaveCookie 是否要保存cookie * @param baseUrl 基础Url * @param url 要拼接的url * @param map 参数集合 * @param callback 请求回调 */ public static void postMethod(boolean isReadCookie, boolean isSaveCookie, String baseUrl, String url, Map<String, String> map, final Callback<String> callback) { OkHttpClient httpClient = null; if (isReadCookie && !isSaveCookie) { httpClient = new OkHttpClient.Builder() .addInterceptor(new ReadCookiesInterceptor()) .build(); Log.i("AAA","只读不写"); } if (isSaveCookie && !isReadCookie) { httpClient = new OkHttpClient.Builder() .addInterceptor(new SaveCookiesInterceptor()) .build(); Log.i("AAA","只写不读"); } if (isSaveCookie && isReadCookie) { httpClient = new OkHttpClient.Builder() .addInterceptor(new SaveCookiesInterceptor()).addInterceptor(new ReadCookiesInterceptor()) .build(); Log.i("AAA","又写又读"); } if (!isSaveCookie && !isReadCookie){ httpClient = new OkHttpClient.Builder() .build(); Log.i("AAA","不写不读"); } //指定客户端 Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl).client(httpClient).addConverterFactory(ScalarsConverterFactory.create()).build();
好了,暂时写到这里,以上就是对Retrofit的一个简易封装,当然网上也有一些大神对Retrofit进行了封装。
参考资料:
Retrofit 使用详解http://blog.csdn.net/duanyy1990/article/details/52139294
Retrofit顶级封装 http://blog.csdn.net/gengqiquan/article/details/52329259
github引用地址 https://github.com/gengqiquan/HttpUtil
相关文章推荐
- Retrofit 最简单的快速入门及封装
- 自己写的封装好的简单的AJAX--javascript
- 流行Java开源数据库框架项目 - Hibernate快速简单入门
- Delphi入门4--自己写代码连接资料库,对数据进行简单操作,还是简单的入门
- ajax的简单应用之快速入门
- Flex 3快速入门: 构建简单的用户界面 控制和使用光标
- Windows 9x /NT 环境下的C程序设计快速入门(从硬盘上翻出来的老早自己写的东西,怀念啊)
- CodeIgniter 入门:快速简单地创建 MVC 应用程序
- 菜鸟快速入门 struts 1.X (简单的登陆)第一篇
- Flex 3快速入门: 构建简单的用户界面 设置组件的样式
- 教你快速掌握一个简单的Oracle定时任务-入门基础
- 自己写的封装好的简单的AJAX--javascript (改良版)
- CodeIgniter 入门:快速简单地创建 MVC 应用程序
- 最简单的C#快速入门
- Flex 3快速入门: 构建简单的用户界面 添加效果
- 自己写的封装好的简单的AJAX--javascript
- 最简单的C#快速入门
- D3D初始化环境 自己封装的一个简单的类
- Flex 3快速入门: 构建简单的用户界面 定义状态过渡
- ajax的简单应用之快速入门