Retrofit使用详解

一、简介

Retrofit是一个RESTful的HTTP网络请求框架的封装,RESTful介绍见博客《RESTful API 最佳实践》。网络请求的工作本质上是OkHttp 完成,Retrofit仅负责网络请求接口的封装。App应用程序通过 Retrofit 请求网络,实际上是使用Retrofit接口层封装请求参数、Header、Url 等信息,之后由OkHttp 完成后续的请求操作。在服务端返回数据之后,OkHttp将原始的结果交给Retrofit,Retrofit根据用户的需求对结果进行解析。

二、使用步骤

1、在build.gradle中添加依赖

compile 'com.squareup.retrofit2:retrofit:2.0.2'

2、在AndroidManifest.xml中添加网络权限

<uses-permission android:name="android.permission.INTERNET" />

3、创建描述网络请求的接口

Retrofit将Http请求抽象成Java接口:采用注解描述网络请求参数和配置网络请求参数,用动态代理将该接口的注解“翻译”成一个Http请求,最后再执行Http请求。注意接口中的每个方法的参数都需要使用注解标注,否则会报错。

新建接口RequestInterface,使用注解标记请求方法和请求url。

public interface RequestInterface {
    @GET("/OkHttpTest/OkHttpServlet")
    Call<String> get();
}

4、创建Retrofit实例

// OkHttp报文打印拦截器
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
    @Override
    public void log(String message) {
        Log.i(TAG, "----http报文:" + message);
    }
});
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

// OkHttp配置
OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .addInterceptor(loggingInterceptor)
        .connectTimeout(10, TimeUnit.SECONDS)
        .readTimeout(10, TimeUnit.SECONDS)
        .writeTimeout(10, TimeUnit.SECONDS)
        .build();

// Retrofit配置
retrofit = new Retrofit.Builder()
        .baseUrl("http://192.168.10.160:8080")
        .client(okHttpClient)
        .addConverterFactory(GsonConverterFactory.create())
        .build();

1)、baseUrl()方法

网络请求的完整Url =创建Retrofit实例时baseUrl()设置 +网络请求接口的注解设置

2)、client()方法

client()设置OkHttp,我们可以配置OkHttp的一些参数,然后通过该方法设置到Retrofit中

3)、addConverterFactory()方法

addConverterFactory设置数据解析器

5、创建网络请求接口实例

RequestInterface requestInterface = retrofit.create(RequestInterface.class);

通过rerequestInterface就可以请求网络了

6、发送网络请求

1)、发送同步请求

Call<String> call = RetrofitUtil.getInstance().getApi().get();
Response<String> response = call.execute();

注意call.execute()必须在子线程调用

2)、发送异步请求

Call<String> call = RetrofitUtil.getInstance().getApi().getAddHeader();
call.enqueue(new Callback<String>() {
    @Override
    public void onResponse(Call<String> call, Response<String> response) {
        if (response.isSuccessful()) {
            tvMsg.append(response.body().toString());
        } else {
            tvMsg.append("response code is " + response.code());
        }
    }

    @Override
    public void onFailure(Call<String> call, Throwable t) {
        tvMsg.append(t.getMessage());
    }
});

call.enqueue()可以直接在主线程中调用

三、Retrofit注解

Retrofit配置Http请求方法、请求地址、请求参数等都是使用注解的方式,因此Retrofit的注解使用非常重要。所有注解统计如下:

1、网络请求方法

标注Http请求的方法

1)、上面的注解只能修饰方法,因为定义注解时设置如下:@Target(METHOD),Target设置时METHOD

2)、使用@GET和@POST

URL通过这些注解后的()传入

public interface RequestInterface {
    @GET("/OkHttpTest/OkHttpServlet")
    Call<String> get();

    @POST("/OkHttpTest/OkHttpServlet")
    Call<String> postBody(@Body RequestBody requestBody);
}

3)、使用@HTTP

替换@GET、@POST、@PUT、@DELETE、@HEAD注解的作用及更多功能拓展,通过属性method、path、hasBody进行设置

public interface RequestInterface {
    @HTTP(method = "GET", path = "/OkHttpTest/OkHttpServlet", hasBody = false)
    Call<String> testHttp();

    @HTTP(method = "POST", path = "/OkHttpTest/OkHttpServlet", hasBody = true)
    Call<String> testHttp(@Body String body);
}

2、标记类注解

标记类注解都是配置方法的

1)、@FormUrlEncoded

表示发送form-encoded的数据,每个键值对需要用@Filed来注解键名,值通过方法的形参传入。

public interface RequestInterface {
    @POST("/OkHttpTest/OkHttpServlet")
    @FormUrlEncoded
    Call<String> postForm(@Field("key1") String value1, @Field("key2") String value2);
}

2)、@Multipart

表示发送form-encoded的数据,适用于文件上传的场景,每个键值对需要用@Part来注解键名,随后的对象需要提供值。

public interface RequestInterface {
    /**
     * @Part后可以用任意类型的对象。是MultipartBody.Part时Part不用指定表单字段名,因为MultipartBody.Part 中已经指定了,其他类型需要指定表单字段名。
     * 使用MultipartBody.Part
     */
    @POST("/OkHttpTest/OkHttpServlet")
    @Multipart
    Call<String> postPart(@Part MultipartBody.Part part);

    /**
     * 使用RequestBody
     */
    @POST("/OkHttpTest/OkHttpServlet")
    @Multipart
    Call<String> postPart(@Part("part1") RequestBody part1, @Part("part2") RequestBody part2);

    /**
     * 使用String
     */
    @POST("/OkHttpTest/OkHttpServlet")
    @Multipart
    Call<String> postPart(@Part("part1") String part1, @Part("part2") String part2);

    /**
     * 使用自定义对象Student
     * 如果转换器是.addConverterFactory(GsonConverterFactory.create())会自动将对象转换为json字符串
     */
    @POST("/OkHttpTest/OkHttpServlet")
    @Multipart
    Call<String> postPart(@Part("part1") Student part1, @Part("part2") Student part2);
}

调用如下:

MultipartBody.Part part = MultipartBody.Part.createFormData("key", "value");
//                MultipartBody.Part part = MultipartBody.Part.create(RequestBody.create(MediaType.parse("text"), "MultipartBody"));
Call<String> partCall = RetrofitUtil.getInstance().getApi().postPart(part);
try {
    partCall.execute();
} catch (IOException e) {
    e.printStackTrace();
}

RequestBody requestBodyPart = RequestBody.create(MediaType.parse("text"), "post body");
partCall = RetrofitUtil.getInstance().getApi().postPart(requestBodyPart, requestBodyPart);
try {
    partCall.execute();
} catch (IOException e) {
    e.printStackTrace();
}

partCall = RetrofitUtil.getInstance().getApi().postPart("part1", "part2");
try {
    partCall.execute();
} catch (IOException e) {
    e.printStackTrace();
}

partCall = RetrofitUtil.getInstance().getApi().postPart(new Student("小王", 18), new Student("小丽", 19));
try {
    partCall.execute();
} catch (IOException e) {
    e.printStackTrace();
}

3、网络请求参数注解

用于标注Http的请求参数,如头、body、form表单数据等

1)、 @Headers

添加请求头,头的信息是固定的,不能通过方法的形参设置。可以添加多个头。

添加一个头

// 添加一个head    
@GET("/OkHttpTest/OkHttpServlet")
@Headers("head1:head1_value")
Call<String> getAddHeader();

添加多个头,头之间用逗号分隔,所有头外面加一个{}

@GET("/OkHttpTest/OkHttpServlet")
@Headers({"Authorization:authorization","head2:head2_value"})
Call<String> getAddHeader();

2)、Header

添加不固定的头,值通过方法的形参设置。

@GET("/OkHttpTest/OkHttpServlet")
Call<String> getAddConfigHeader(@Header("config_header") String header);

@Header注解中配置的是头的key

3)、Body

4)、@Field

向post请求的表单中传入键值对。@Field注解中指定键名

@POST("/OkHttpTest/OkHttpServlet")
@FormUrlEncoded
Call<String> postForm(@Field("key1") String value1, @Field("key2") String value2);

5)、@FieldMap

向post请求的表单中传入键值对。适合键值对比较多的情况,传入的形参是Map。Form表单中的键值对就是Map中的键值对。

@POST("/OkHttpTest/OkHttpServlet")
@FormUrlEncoded
Call<String> postFormMap(@FieldMap Map<String, String> map);

6)、@Part

适合文件上送的场景。

@POST("/OkHttpTest/OkHttpServlet")
@Multipart
Call<String> postPart(@Part("part1") RequestBody part1, @Part("part2") RequestBody part2);

详见上面 三——2——(2)

7)、@PartMap

适合上送Part比较多的场景。

@POST("/OkHttpTest/OkHttpServlet")
@Multipart
Call<String> postPartMap(@PartMap Map<String, RequestBody> map);

8)、@Query

@GET("/OkHttpTest/OkHttpServlet")
Call<String> getWithQueryParam(@Query("query") String query);
@POST("/OkHttpTest/OkHttpServlet")
Call<String> getWithQueryParam(@Query("query") String query);

使用get和post都可以,都是生成key=values&key=value的形式,添加到url后面。生成的数据和@Field是一样的,区别是@Query数据添加到url后面,@Post数据添加到body中。

9)、@QueryMap

适合键值对比较多的情况。

@GET("/OkHttpTest/OkHttpServlet")
Call<String> getWithQueryParams(@QueryMap Map<String, String> map);

10)、@Path

用于实现动态设置url中某个path

@GET("/OkHttpTest/OkHttpServlet/{user}")
Call<String> getConfigPath(@Path("user") String user);

{user}指定可以被设置的path,形参会替换{user}

11)、@URL

用于实现动态配置url,在@GET注解中不设置url,在形参中设置,这样就可以动态改变url

@GET
Call<String> getConfigUrl(@Url String url, @Query("query1") String query);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值