Retrofit 最简单的快速入门及自己封装

简单介绍及官方文档的坑

  • 官方文档 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> 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> 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 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 baidu = dataService.baidu("http://wwww.baidu.com");
        //执行异步请求
        baidu.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                Toast.makeText(MainActivity.this,  response.body(), Toast.LENGTH_SHORT).show();
            }
            @Override
            public void onFailure(Call call, Throwable t) {

            }
        });
  • 通过上述代码,咱们就可以完整的看见百度的html界面了,算是对Retrofit做一个入门

其他请求-QQ吉凶测试

  • 第三方网站聚合数据上的测试地址,key有可能过期,大家测的时候可以自己申请key 官网 https://www.juhe.cn

    http://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 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 = dataService.getQQData("96efc220a4196fafdfade0c9d1e897ac", "11111111");
        qqData.enqueue(new Callback() {
            @Override
            public void onResponse(Response 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 getMethod(@Url String url);

    @FormUrlEncoded
    @POST
    Call postMethod(@Url String url, @FieldMap Map 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 callback) {
        Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl).addConverterFactory(ScalarsConverterFactory.create()).build();

        ProjectAPI projectAPI = retrofit.create(ProjectAPI.class);

        Call call = projectAPI.getMethod(url);
        call.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
            //调用回调
                callback.onResponse(call, response);
            }

            @Override
            public void onFailure(Call 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() {
            @Override
            public void onResponse(Call call, Response response) {
                Toast.makeText(MainActivity.this, "--"+response.body(), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onFailure(Call 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 map, final Callback 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

你可能感兴趣的:(框架进阶)