Retrofit 菜鸟必入

一、添加依赖

在Module的build.gradle中添加如下依赖:

    //retrofit
    compile 'com.squareup.retrofit2:retrofit:2.0.2'
    //retrofit  String的转换器
    compile 'com.squareup.retrofit2:converter-scalars:2.1.0'
    //retrofit   Gson的转换器
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    //retrofit    返回值的adapter的转化器,为了于RxJava配合使用
    compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0'

二、Get请求

我在这里只讲Get请求和Post请求,因为其他的请求没用过。

  • 1、首先我们将我们要访问的地址URL分成两个部分
如:
//我们要访问的地址
http://www.xxx.com/api/rest/session
//基地址
http://www.xxx.com/api/rest/
//剩下的部分
session

注意
retrofit2.0之后的baseUrl必需以/(斜线)结束,否则会报IllegalArgumentException异常

  • 2、创建接口并定义方法

说明: 看见Call是不是感觉眼熟,是不是想起了Okhttp3,retrofit默认返回的就是Call < ResponseBody>类型(okhttp3.ResponseBody这个包);至于怎么转变为想要的类型接下来慢慢说。

/**
 *
 * 注解说明:
 *
 * 标记:
 * 
 * 1、FormUrlEncoded 注解:表示请求体是一个Form表单;
 *
 * 2、Multipart 注解:表示请求体是一个支持文件上传的Form表单;
 *
 * 3、Streaming 注解:表示响应体的数据用流的形式返回,如果,没有用该注解,默认会吧数据存在内存,之后通过流读取数据也是读内存中的数据,如果数据比较大,建议使用该注解。
 *
 * 参数:
 *
 * 1、Headers:用于添加请求头
 *
 * 2、Header:用于添加不固定值的Header
 *
 * 3、Body:用于非表单请求体
 *
 * 4、Field、FieldMap、Part、PartMap:用于表单字段
 *
 *      Field、FieldMap与FormUrlEncoded配合使用;
 *      Part、PartMap与Multipart配合使用,适合有文件上传的情况;
 *
 *      FieldMap:接受的类型为Map<String,String>;
 *      PartMap默认接受的类型为Map<String,RequestBody>.
 *
 * 5、Path、Query、QueryMap、Url:用于URL
 *
 *      Query、QueryMap中的数据体现在URL上,Field、FieldMap的数据是请求体,但是两者生成的数据形式是一样的。
 * 
 * @Get("")中一定要有参数,否则会报错
 */
public interface MyService {

    @Headers("X-Oc-Merchant-Id:1qaz2wsx")
    @GET("session")
    Call<ResponseBody> getSessionResponseBody();

    }
  • 3、使用接口

注意:回调是主线程、主线程、主线程

/**
     * 在默认情况下Retrofit只支持将HTTP的响应体转换为ResponseBody
     */
    private void retrofitResponseBody() {
        //得到retrofit,并设置相应的基地址,别忘了调用build()
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.xxx.com/api/rest/")
                .build();

        //通过retrofit得到接口
        MyService myService = retrofit.create(MyService.class);

        //通过接口调用刚才定义的方法,看到了吧,这个返回值为call
        Call<ResponseBody> call = myService.getSessionResponseBody();

        //然后和okhttp一样调用enqueue,这个是异步,这里要注意哈,回调是主线程,和okhttp不一样,切记、切记、切记
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                try {
                    Log.e("------------>", "response" + response.body().string());

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {

            }
        });
    }

三、Get请求,使用Converter转换ResponseBody

---->转换为String,或者Gson解析的对象

我这里说的转换为String,不单单是String,而是Call< String>,转换为对象也是同理。这里需要引入一个新的东西Converter转换器,在添加依赖的时候应该看到了,有一个转为String的转换器的依赖,官方还提供了其他的几个,这里我只添加了String和Gson的。

  • 1、先看看接口
//我这个里面都添加了头,这个是我门接口的要求,可根据自己的需求添加
purlic interface MyService{

    @Headers("X-Oc-Merchant-Id:dsdsdsdsds")
    @GET("session")
    Call<String> getSession();

    @GET("session")
    @Headers("X-Oc-Merchant-Id:dsdsdsdsds")
    Call<Session> getSessionGson();
}
  • 2、使用

步骤还是上面的那些,这里我就简化了,一只.下去了(链式)

private void retrofitGet() {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.xxx.com/api/rest/")
                .addConverterFactory(ScalarsConverterFactory.create())//增加返回值为String的支持
                .addConverterFactory(GsonConverterFactory.create())//Gson转换器
                .build();

        //创建接口文件
        MyService myService = retrofit.create(MyService.class);

        //返回数据是String
        myService.getSession().enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                Log.e("----------->", "response" + response.body() + ",message:" + response.message() + "当前线程:" + Thread.currentThread().getName());
            }

            @Override
            public void onFailure(Call<String> call, Throwable t) {

            }
        });

        //返回的数据是Session类型
        myService.getSessionGson().enqueue(new Callback<Session>() {
            @Override
            public void onResponse(Call<Session> call, Response<Session> response) {
                Session session = response.body();
                Log.e("------------->", "requestbody  session" + session.getData().getSession() + "success:" + response.body().getSuccess() + ",message:" + response.message());
            }

            @Override
            public void onFailure(Call<Session> call, Throwable t) {

            }
        });
    }
  • 3、说明:

这里可以看到我在创建retrofit的时候,不光添加了基地址还多了两行

//增加返回值为String的支持 .addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create()) //Gson转换器 
  • 4、注意

如果返回的类型不是ResponseBody,还不加上面两句话,会报如下异常:

java.lang.IllegalArgumentException: Unable to create converter for class java.lang.String异常

四、GET请求,@Path和@Query

  • 1、接口

同样我都写在了MyService中

下面的两个URL为:

http://www.xxx.com/api/rest/products?id= 65
http://www.xxx.com/api/rest/products/{product_id}//将product_id替换为65
    /**
     * 会将id拼接在URL后面及?id=传进来的值
     * @param id
     * @return
     */
    @GET("products")
    @Headers("X-Oc-Merchant-Id:1qaz2wsx")
    Call<String> getProductDetial(@Query("id") String id);

    /**
     * 直接将路径中的进行替换,{xxxx}就相当于占位符,然后直接用参数替代就可以了
     * @param product_id
     * @return
     */
    @GET("products/{product_id}")
    @Headers("X-Oc-Merchant-Id:1qaz2wsx")
    Call<String> getProductDetialPath(@Path("product_id")String product_id);
  • 2、使用
/**
     * 查询参数的设置
     * 
     * 如果Query参数比较多,那么可以通过@QueryMap方式将所有的参数集成在一个Map统一传递
     */
    private void retrofitGetQuery() {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.xxx.com/api/rest/")
                .addConverterFactory(ScalarsConverterFactory.create())
                .build();


        MyService myService = retrofit.create(MyService.class);
        myService.getProductDetial("65").enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                Log.e("------------>", "response" + response.body());
            }

            @Override
            public void onFailure(Call<String> call, Throwable t) {
                Log.e("------------>", "t" + t);
            }
        });
    }

    /**
     * get请求
     * 
     * 说明@Path和@Query的区别:
     * 
     * 1、@Path:http://www.xxx.com/api/rest/products?id=65   ----->主要定位在路径上
     * 
     * 2、@Query:http://www.xxx.com/api/rest/products/{product_id} (把{product_id}直接写成65) ------->主要定位在参数上
     * 
     * {占位符}和PATH尽量只用在URL的path部分,url中的参数使用Query和QueryMap 代替
     */
    private void retrofitGetPath() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.xxx.com/api/rest/")
                .addConverterFactory(ScalarsConverterFactory.create())
                .build();

        MyService myService = retrofit.create(MyService.class);

        myService.getProductDetialPath("65").enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                Log.e("------------>", "response" + response.body());
            }

            @Override
            public void onFailure(Call<String> call, Throwable t) {
                Log.e("------------>", "t" + t);
            }
        });
    }

五、Post请求参数为Json类型及使用@Body

  • 1、接口

上面也说过,非表单的参数使用@Body

请求头我们可以添加多个
/**
     * post请求参数类型是json
     * @param requestBody
     * @return
     */
    @POST("cart?from=cart")
    @Headers({
            "X-Oc-Merchant-Id:1qaz2wsx",
            "X-OC-SESSION:8cn12jj6bruv5iemtuq0q43461",
            "Content-Type:application/json"
    })
    Call<String> postBody(@Body RequestBody requestBody);
  • 2、使用
/**
     * post请求,参数是json类型的时候
     */
    private void retrofitPostJson() {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.xxx.com/api/rest/")
                .addConverterFactory(ScalarsConverterFactory.create())
                .build();

        MyService myService = retrofit.create(MyService.class);
        Map<String, String> params = new HashMap<>();
        params.put("product_id", "65");
        params.put("quantity", "2");
        params.put("option", "");
        params.put("recurring_id", "0");

        //使用Gson将map转为json字符串
        String json = new Gson().toJson(params);
        Log.e("------------>", "json" + json);
        //使用okHttp中的MediaType创建RequestBody
        myService.postBody(RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json)).enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                Log.e("----------->", "responseffff" + response.body());
            }

            @Override
            public void onFailure(Call<String> call, Throwable t) {

            }
        });

    }
  • 3、说明

在学okHttp的时候我们可以将包含普通表单、json、以及包含文件的数据,放到RequestBody中当参数,所以这里也这么使用。也就明白,接口中的参数为啥为RequestBody类型了。

六、Post请求,参数为Map及使用@FieldMap

及post的请求参数是map类型

  • 1、接口

注意要加上@FormUrlEncoded标记

   /**
     * post请求FormUrlEncoded和FieldMap配合使用
     * @param id
     * @param params
     * @return
     */
    @FormUrlEncoded
    @POST("healthplan/plans/{id}")
    Call<String> postFieldMap(@Path("id") String id,@FieldMap Map<String,String> params);
  • 2、使用
 /**
     * post请求使用@FieldMap,参数是Map类型的
     */
    private void retrofitPostFieldMap() {

        Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(ScalarsConverterFactory.create())
                .baseUrl("http://app.xxx.com/v1.0.0/")
                .build();


        Map<String, String> map = new HashMap<>();

        map.put("nickName", "单线程");
        map.put("reResourceUrl", "");
        map.put("reResourceId", "");
        retrofit.create(MyService.class).postFieldMap("169", map).enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                Log.e("------------>", "response" + response.body());
            }

            @Override
            public void onFailure(Call<String> call, Throwable t) {
                Log.e("------------>", "t" + t);
            }
        });
    }

你真的会用Retrofit2吗?Retrofit2完全教程

在添加转换器的时候是不是看到了一个和那个方法长得很像的方法,那个方法就可以让你和RxAndroid 一起使用了,继续往下看吧。

猜你喜欢

转载自blog.csdn.net/hello_1s/article/details/76665040