概览

Retrofit 是一个Square开发的类型安全的REST安卓客户端请求库。这个库为网络认证、API请求以及用OkHttp发送网络请求提供了强大的框架 。理解OkHttp 的工作流程见  这个指南 。

注意本文是基于Retrofit2.0讲解的 - 译者注。

Retrofit 库让从web api下载JSON 或者xml数据变的非常简单直接。一旦数据下载完成即将其解析成普通java类(POJO)。

设置

首先确保在AndroidManifest.xml中请求了网络权限 :

  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2. <uses-permission android:name="android.permission.INTERNET" />
  3. </manifest>

在app/build.gradle文件中添加如下代码:

  1. dependencies {
  2. compile 'com.google.code.gson:gson:2.3'
  3. compile 'com.squareup.retrofit:retrofit:2.0.0-beta1'
  4. compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
  5. compile 'com.squareup.okhttp:okhttp:2.4.0'
  6. }

过去,Retrofit 依赖于Gson 库来解析JSON数据。 Retrofit 2 现在支持许多种解析方式来解析响应数据,包括 Moshi,一个由Square 创建的高效JSON解析库。

但是,它也存在一些 局限,,因此如果你不确定该使用哪种,就暂时使用Gson converter 吧。

有如下的解析库可以选择:

Converter Library
Gson com.squareup.retrofit:converter-gson:2.0.0-beta2
Jackson com.squareup.retrofit:converter-jackson:2.0.0-beta1
Moshi com.squareup.retrofit:converter-moshi:2.0.0-beta1
Protobuf com.squareup.retrofit:converter-protobuf:2.0.0-beta1
Wire com.squareup.retrofit:converter-wire:2.0.0-beta1
Simple XML com.squareup.retrofit:converter-simplexml:2.0.0-beta1

要能把json解析成数据对象,需要响应的Java对象(准确的讲是类),因此我们需要先自己构造Java对象。

从资源中创建Java对象

本文讨论了两种方法。第一种是手动创建,这要求你学会如何使用 Gson 库。第二种是自动生成,使用jsonschema2pojo。我们建议你使用手动的方式,因为这样你能更好的理解自动生成代码是如何工作的。

手动方式创建Java对象

这篇指南 讲述了关于如何利用Gson库创建自己的数据对象来供Retrofit使用。它演示了如何使用Gson 接收来自Rotten Tomatoes API的数据,但是对于其他RESTful web service方法是相同的。

自动生成Java对象

假设你已经有了JSON的响应结果,访问jsonschema2pojo

你可以选择注解方式为Gson,但这并不是完全必须的,因为java没有它们也能工作。目前,我们暂且选择None作为注解方式。(Retrofit1.9默认使用的是Gson解析,如果要和Retrofit一起使用,注解方式请选择Gson。不然生成的驼峰命名方式会导致解析失败)

接下来,把JSON 输出粘贴到文字输入框中:

点击Preview 按钮。你可以看到前面部分和下图类似:

把生成的类粘贴到项目的诸如models一类的子包之下,把类名Example重命名为反映数据模型的名称。以这里为例,我们命名为User。

注意:生成的代码中存在@Generated注解。安卓默认并没有javax.annotation library里面的许多东西。如果你希望保留@Generated注解,你需要添加如下的依赖。更多信息参见Stack Overflow上的讨论。或者,你可以直接删除这个注解,完全没有问题。

  1. dependencies {
  2. provided 'org.glassfish:javax.annotation:10.0-b28'
  3. }

创建Retrofit 实例

要向一个api发送我们的网络请求 ,我们需要使用 Retrofit builder 类并指定service的base URL (通常情况下就是域名)。

  1. public static final String BASE_URL = "http://api.myservice.com";
  2. Retrofit retrofit = new Retrofit.Builder()
  3. .baseUrl(BASE_URL)
  4. .addConverterFactory(GsonConverterFactory.create())
  5. .build();

还需注意我们要指定一个factory 来对响应进行反序列化,使用的是 Gson library。就如这个视频演讲中所说的,converters 被添加的顺序将是它们被Retrofit尝试的顺序。如果我们希望传入一个自定义的Gson 解析实例,也是可以指定的:

  1. Gson gson = new GsonBuilder()
  2. .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
  3. .create();
  4. Retrofit retrofit = new Retrofit.Builder()
  5. .baseUrl(BASE_URL)
  6. .addConverterFactory(GsonConverterFactory.create(gson))
  7. .build();

添加多个converters - 译者注。

定义 Endpoints

在Retrofit 2中,endpoints是定义在一个interface里面的(其实1.9版本也是,只是用法略有不同),使用特殊的retrofit 注解来映射参数以及请求方法这些细节。另外,返回值始终是一个参数化了的Call<T>对象,比如Call<User>。如果你不需要任何类型安全的响应,你可以把返回值指定为Call<Response>。

比如,这个interface 用下面的方式定义了每个endpoint :

  1. public interface MyApiEndpointInterface {
  2. // Request method and URL specified in the annotation
  3. // Callback for the parsed response is the last parameter
  4. @GET("/users/{username}")
  5. Call<User> getUser(@Path("username") String username);
  6. @GET("/group/{id}/users")
  7. Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
  8. @POST("/users/new")
  9. Call<User> createUser(@Body User user);
  10. }

注意到每个endpoint 都指定了一个关于HTTP(GET, POST, 等等。)  方法的注解以及用于分发网络调用的方法。而且这些方法的参数也可以有特殊的注解。

注解 描述
@Path variable substitution for the API endpoint (i.e. username will be swapped for {username} in the URL endpoint).
@Query specifies the query key name with the value corresponding to the value of that annotated parameter.
@Body payload for the POST call

修改 base URL

一般地,base URL是在实例化 Retrofit instance的时候定义的。Retrofit 2 允许你在注解里面重写base URL 。

  1. @POST("https://api.github.com/api/v3")

就如 这篇文章(中文地址: Retrofit 2.0)所讨论的,还有一些允许你使用相对路径(不是完整的URL)修改 base URL的方法。

Multipart forms

如果你要提交多参数表单数据(multi-part form data),可以使用@Multipart与@Part注解:

  1. @Multipart
  2. @POST("/some/endpoint")
  3. Call<SomeResponse> someEndpoint(@Part("name1") String name1, @Part("name2") String name2)

Form URL encoding

如果我们希望提交 form-encoded name/value ,我们可以使用@FormUrlEncoded 与 @FieldMap注解:

  1. @FormUrlEncoded
  2. @POST("/some/endpoint")
  3. Call<SomeResponse> someEndpoint(@FieldMap Map<String, String> names);

Upgrading from Retrofit 1

如果你是想从 Retrofit 1升级过来,你应该记得在1.x版本中,如果你想定义一个异步的API请求而非同步请求,最后一个参数必须是Callback类型:

  1. public interface MyApiEndpointInterface {
  2. // Request method and URL specified in the annotation
  3. // Callback for the parsed response is the last parameter
  4. @GET("/users/{username}")
  5. void getUser(@Path("username") String username, Callback<User> cb);
  6. @GET("/group/{id}/users")
  7. void groupList(@Path("id") int groupId, @Query("sort") String sort, Callback<List<User>> cb);
  8. @POST("/users/new")
  9. void createUser(@Body User user, Callback<User> cb);
  10. }

Retrofit 1 依赖于这个Callback类型作为最后一个参数,决定api请求是异步的。为了避免出现两种不同的调用模式,这个接口在Retrofit 2被统一了。现在你可以直接定义返回值为一个参数化了的Call<T>,如前面小节所讲。

Accessing the API

我们现在可以把这些东西放在一起:

  1. MyApiEndpointInterface apiService =
  2. retrofit.create(MyApiEndpointInterface.class);

如果我们想异步请求这个API,我们如下调用这个service (注意取名为service 是Retrofit 的惯例,并不是语法的一部分):

  1. String username = "sarahjean";
  2. Call<User> call = apiService.getUser(username);
  3. call.enqueue(new Callback<User>() {
  4. @Override
  5. public void onResponse(Response<User> response) {
  6. int statusCode = response.code();
  7. User user = response.body();
  8. }
  9. @Override
  10. public void onFailure(Throwable t) {
  11. // Log error here since request failed
  12. }
  13. });

如上所示,Retrofit 将在后台线程下载与解析API数据,然后通过onResponse或者 onFailure方法把结果发送回UI线程。

同步请求呢?更简单,是这样的:

  1. // Synchronous Call in Retrofit 2.0
  2. String username = "sarahjean";
  3. Call<User> call = apiService.getUser(username);
  4. User user = call.execute();

Retrofit与Authentication

使用Authentication Headers

可以使用一个Interceptor来为请求添加Headers。要发送请求到一个authenticated API,如下:

  1. // Define the interceptor, add authentication headers
  2. Interceptor interceptor = new Interceptor() {
  3. @Override
  4. public Response intercept(Chain chain) throws IOException {
  5. Request newRequest = chain.request().newBuilder().addHeader("User-Agent", "Retrofit-Sample-App").build();
  6. return chain.proceed(newRequest);
  7. }
  8. };
  9. // Add the interceptor to OkHttpClient
  10. OkHttpClient client = new OkHttpClient();
  11. client.interceptors().add(interceptor);
  12. // Set the custom client when building adapter
  13. Retrofit retrofit = new Retrofit.Builder()
  14. .baseUrl("https://api.github.com")
  15. .addConverterFactory(GsonConverterFactory.create())
  16. .client(client)
  17. .build();

注意在Retrofit 2中,interceptor 必须添加到一个自定义的OkHttpClient。而在Retrofit 1,它可以直接被builder 类设置。

使用 OAuth

为了用OAuth来认证,我们需要为每个网络请求注册一个特殊的header ,这个header 嵌入了在认证过程中为用户获取的access token。实际的认证过程需要使用第三方的library(比如signpost )完成,然后使用一个request interceptor把 access token添加到header中。Retrofit与authentication的相关链接列举如下:

使用signpost认证的资料:

其它替代signpost的Android OAuth 库:

参考

Android 使用Retrofit请求API数据的更多相关文章

  1. Android - 使用Volley请求网络数据

    Android - 使用Volley请求网络数据 Android L : Android Studio 14 个人使用volley的小记,简述使用方法,不涉及volley源码 准备工作 导入Volle ...

  2. 关于ajax跨域请求API数据的一些问题

    一般来说我们使用jquery的ajax来跨域请求API数据的时候每次请求,就只能请求一组数据,而且当我们再次点击发送ajax请求的时候,新请求的数据会覆盖掉原来的数据,那么如何每次在请求的数据的时候, ...

  3. android 获取http请求json数据

    package com.my.gethttpjsondata; import java.io.BufferedReader;import java.io.ByteArrayOutputStream;i ...

  4. Android 使用Retrofit获取JSON数据

    在大家使用网络请求的时候,往往会出现一种情况:需要拿到服务器返回来的JSON字符串,而Retrofit会默认将Json解析,而又没有直接暴露出拿到Json字符串的方法: 今天测接口的时候,发现当数据正 ...

  5. APICloud ajax请求api数据问题

    云编译开启全局加密的情况下,请务必使用api.ajax,避免使用JQ等框架的ajax,否则将引起请求失败.官网API说明链接 还要就是要注意用$.ajax请求数据时会出现的同源策略问题.

  6. Android okHttp网络请求之Retrofit+Okhttp+RxJava组合

    前言: 通过上面的学习,我们不难发现单纯使用okHttp来作为网络库还是多多少少有那么一点点不太方便,而且还需自己来管理接口,对于接口的使用的是哪种请求方式也不能一目了然,出于这个目的接下来学习一下R ...

  7. Android之三种网络请求解析数据(最佳案例)

    AsyncTask解析数据 AsyncTask主要用来更新UI线程,比较耗时的操作可以在AsyncTask中使用. AsyncTask是个抽象类,使用时需要继承这个类,然后调用execute()方法. ...

  8. 基于Retrofit+RxJava的Android分层网络请求框架

    目前已经有不少Android客户端在使用Retrofit+RxJava实现网络请求了,相比于xUtils,Volley等网络访问框架,其具有网络访问效率高(基于OkHttp).内存占用少.代码量小以及 ...

  9. Android网络请求与数据解析,使用Gson和GsonFormat解析复杂Json数据

    版权声明:未经博主允许不得转载 一:简介 [达叔有道]软件技术人员,时代作者,从 Android 到全栈之路,我相信你也可以!阅读他的文章,会上瘾!You and me, we are family ...

随机推荐

  1. 【BZOJ 1005】[HNOI2008]明明的烦恼(暴力化简法)

    [题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1005 [题意] 中文题 [题解] 一棵节点上标有序号的树会和一个prufer数列唯一对 ...

  2. Mysql学习总结(21)——MySQL数据库常见面试题

    1. 如何使用SELECT语句找到你正在运行的服务器的版本并打印出当前数据库的名称? 答:下面的语句的结果会显示服务器的版本和当前的数据库名称 mysql> SELECT VERSION(), ...

  3. 对jvm进行gc的时间、数量、jvm停顿时间的监控

    在jdk中一个类可以获得gc的信息: public static void main(String[] args) { List<GarbageCollectorMXBean> garba ...

  4. angularjs 路由 ngRoute tab切换

    <!DOCTYPE HTML> <html ng-app="myApp"> <head> <meta http-equiv="C ...

  5. Thinkphp5.0怎么加载css和js

    Thinkphp5.0怎么加载css和js 问题 http://localhost/手册上的那个{load href="/static/css/style.css" /} 读取不到 ...

  6. Python: PS 图像调整--黑白

    本文用Python 实现 PS 里的图像调整–黑白,PS 里的黑白并不是简单粗暴的将图像转为灰度图,而是做了非常精细的处理,具体的算法原理和效果图可以参考以前的博客: http://blog.csdn ...

  7. Objects are mutable

    We can change the state of an object by making an assignment to one of its attributes. For example, ...

  8. Windows安装PHP MongoDB扩展

    本文将讲述一下在Wamp环境下安装MongoDB扩展的过程,大家可以略作参考 Linux 版本的可以参考之前发布的Linux安装PHP MongoDB扩展 安装环境 系统环境:Windows 7 64 ...

  9. BZOJ 3524主席树裸题 (雾)

    思路: 按权值建一棵主席树 (但是这好像不是正解 空间复杂度是不对的--.) //By SiriusRen #include <cstdio> #include <cstring&g ...

  10. 编译报错一列----aclocal找不到

    编译源码包报错: 说aclocal这个命令找不到 解决: 使用 yum install -y automake问题解决