Retrofit2 使用方法

Retrofit2

网络客户端框架

资料

Github
官网

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

配置

导入

  • 配置模组的 build.gradle
compile 'com.squareup.retrofit2:retrofit:2.2.0'
compile 'com.squareup.retrofit2:converter-gson:2.2.0' // 使用Gson转换json
compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0' // 使用RxJava2

混淆

# Platform calls Class.forName on types which do not exist on Android to determine platform.
-dontnote retrofit2.Platform
# Platform used when running on Java 8 VMs. Will not be used at runtime.
-dontwarn retrofit2.Platform$Java8
# Retain generic type information for use by reflection by converters and adapters.
-keepattributes Signature
# Retain declared checked exceptions for use by a Proxy instance.
-keepattributes Exceptions

基本用法

  • Bean和请求接口 -> Retrofit 实例 -> 网络请求 -> 响应处理
// Bean
public class Repo {
    public long id;
    public String name;
}

// 请求接口
public interface GitHubService {
    @GET("users/{user}/repos")
    Call<List<Repo>> listRepos(@Path("user") String user);
}

// Retrofit 实例
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.github.com/")  // 主机
        .addConverterFactory(GsonConverterFactory.create())  // 转换器
        .build();

// 网络请求
Call<List<Repo>> call = retrofit.create(GitHubService.class)  // 获取服务
        .listRepos("octocat"); // 获取请求

// 响应处理,异步或同步
call.enqueue(new Callback<List<Repo>>() {  // 获取响应
    @Override
    public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
        if (response.isSuccessful()) {  // 响应码 200~300
            Log.d(TAG, "onResponse: " + response.body()); // 显示 List<Repo>
        }
    }

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

    }
});

请求接口

请求方法

  • 注解请求方法和相对地址
  • 也可以使用完整地址
  • @GET/@POST/@PUT/@DELETE/@HEAD
@GET("users/list")
@GET("users/list?sort=desc")

请求参数

  • @Path/@Query/@QueryMap/@Url
  • @Query参数为 null,会自动忽略
// 通过 @Path 替换相对地址中的 {}
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);

// 通过 @Query 设置请求参数
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);

// 通过 @QueryMap 设置请求参数 Map
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);

请求头

  • @Headers
  • 请求头不会覆盖,同名头都会包含进请求头
@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call<List<Widget>> widgetList();

@Headers({
    "Accept: application/vnd.github.v3.full+json",
    "User-Agent: Retrofit-Sample-App"
})
@GET("users/{username}")
Call<User> getUser(@Path("username") String username);
  • 动态请求头
  • 值为 null,请求头被删除,否则值调用 toString()
  • 所有请求都需要的请求头,使用 OkHttp interceptor 添加
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)

请求体

  • @Body 非表单请求体
  • 可以指定 Retrofit 的转换器转化请求体,如果没有就使用 RequestBody
@POST("users/new")
Call<User> createUser(@Body User user);
  • 表单标记 @FormUrlEncoded/@Multipart
  • 表单请求体 @Field/@FieldMap/@Part/@PartMap
@FormUrlEncoded  // Form表单
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);

@Multipart  // 上传文件表单
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);

其他

  • 返回流 @Streaming,大数据使用。默认保存在内存里

Retrofit 设置

转换器

  • ResponseBody 为默认响应体类型,即 Call<ResponseBody>,可设置转换器转换

  • Gson: com.squareup.retrofit2:converter-gson

  • Jackson: com.squareup.retrofit2:converter-jackson

  • Moshi: com.squareup.retrofit2:converter-moshi

  • Protobuf: com.squareup.retrofit2:converter-protobuf

  • Wire: com.squareup.retrofit2:converter-wire

  • Simple XML: com.squareup.retrofit2:converter-simplexml

  • Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

Gson gson = new GsonBuilder()
        .setDateFormat("yyyy-MM-dd hh:mm:ss")  // 配置 Gson
        .create();

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com")
    .addConverterFactory(GsonConverterFactory.create(gson))  // 设置转换器,可传入Gson实例
    .build();

GitHubService service = retrofit.create(GitHubService.class);

OkHttpClient

  • Retrofit 持有单独的 OkHttpClient,故设置共用的自定义 OkHttpClient
HttpLoggingInterceptor logging = new HttpLoggingInterceptor()
        .setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient httpClient = new OkHttpClient.Builder()
        .addInterceptor(logging)
        .build();
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.github.com/")
        .client(httpClient)
        .build();

CallAdapter

  • Rxjava com.squareup.retrofit2:adapter-rxjava
  • Guava com.squareup.retrofit2:adapter-guava
  • Java8 com.squareup.retrofit2:adapter-java8

其他

  • callbackExecutor(Executor) 指定Call.enqueue时使用的Executor,只对返回值为Call的方法有效
  • validateEagerly(boolean) 是否在调用create(Class)时检测接口定义是否正确,而不是在调用方法才检测,适合在开发、测试时使用

响应处理

  • execute/enqueue 同步/异步
  • cancel 取消
  • clone 克隆
// 异步
call.enqueue(new Callback<List<Repo>>() {
    @Override
    public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {

    }

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

    }
});

// 同步
try {
    Response<List<Repo>> response = call.execute();
} catch (IOException e) {
    e.printStackTrace();
}

// 取消 Call
call.cancel();

联合 Rxjava

  • Bean和请求接口 -> Retrofit 实例 -> 网络观察者 -> 数据处理
// Bean
public class Repo {
    public long id;
    public String name;
}

// 请求接口
public interface GitHubService {
    @GET("users/{user}/repos")
    Observable<List<Repo>> listReposBy(@Path("user") String user);
}

// Retrofit 实例
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.github.com/")
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())  // 转换器
        .build();

// 网络观察者
Observable<List<Repo>> observable = retrofit.create(GitHubService.class)
        .listReposBy("octocat");

// 数据处理
observable.subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Consumer<List<Repo>>() {
            @Override
            public void accept(@NonNull List<Repo> repos) throws Exception {
                Log.d(TAG, "Rxjava2 - onResponse: " + repos);
            }
        });
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容