Retrofit入门笔记

项目中网络访问模块经历了从AsyncHttp -> OkHttp的变迁,目前方案是对OkHttp做了一层简单封装,主要是结合业务逻辑,完成错误处理、Json解析以及线程切换。现在看来有点惨不忍睹,没能做到高内聚和全面考虑扩展性…
对Retrofit听闻好久,但一直未能完整地学习使用,希望借Retrofit完成更清晰的访问层实现。
Retrofit是一套RESTful规范的Android客户端实现,RESTful常见于API设计,意思是“表现层状态转移”,要求URL全部名词化..(若难以理解,可移步REST解释)。个人理解是,Retrofit将网络访问细节封装,将“去服务器请求数据”的过程转化为“通过接口方法获得数据”,因此Retrofit的使用主要是“请求接口”的定义。

使用

依赖

先引入Retrofit三方库到自己的项目,这里使用gradle方式,而且以Retrofit 2.0.0为主。另外,请求后的数据解析需要Converter来转换为Java对象,这里使用Square提供的GsonConverter。

dependencies {  
// Retrofit
compile 'com.squareup.retrofit2:retrofit:2.0.0'
compile 'com.squareup.retrofit2:converter-gson:2.0.0'
}

注意从Retrofit 2开始,OkHttp就已经集成在里面了,而且不同于1.x支持各种网络引擎,OkHttp是唯一的HttpClient,因此从Retrofit 2包的体积也有所减少。

入门

推荐封装一个ServiceGenerator,便于根据日后为不同API所写的Intrface生成API实现类。

public class ServiceGenerator {

public static final String API_BASE_URL = "http://your.api-base.url";

private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

private static Retrofit.Builder builder =
        new Retrofit.Builder()
                .baseUrl(API_BASE_URL)
                .addConverterFactory(GsonConverterFactory.create());

public static <S> S createService(Class<S> serviceClass) {
    Retrofit retrofit = builder.client(httpClient.build()).build();
    return retrofit.create(serviceClass);
}
}

可以看到,访问引擎为OkHttpClient,且支持自定义(超时、缓存设置等),使用默认的GsonConverter。createService方法则是为了生成独有API而使用,见下。
比如现在要请求Github仓库数据,url为

https://api.github.com/repos/{owner}/{repo}/contributors

创建该API对应访问接口:

public interface GitHubClient {  
@GET("/repos/{owner}/{repo}/contributors")
Call<List<Contributor>> contributors(
    @Path("owner") String owner,
    @Path("repo") String repo
);
}

可以看出,注解@GET指定了Http访问方式,后面的url是基于BASE_URL的相对路径,Retrofit会将他们拼接后访问。
再看contributors方法,不难看出owner/repo作为参数替换了相对路径中的{owner}/{repo}。当然,@PATH只是最简单的路径替换。更复杂的url拼接和Headers的定义Retrofit当然也可以胜任,下文会描述。
调用如下:

public static void main(String... args) {  
// Create a very simple REST adapter which points the GitHub API endpoint.
GitHubClient client = ServiceGenerator.createService(GitHubClient.class);

// Fetch and print a list of the contributors to this library.
Call<List<Contributor>> call =
    client.contributors("fs_opensource", "android-boilerplate");

最后执行,注意要求在子线程:

List<Contributor> contributors = call.execute().body();

关键在于得到Call对象,接着子线程执行execute方法即可完成网络访问,Gson负责将Response中实体内容解析并返回相应对象。

小结

以上,可以看出Retrofit使用注解方式定义API真是异常的方便,常用的annotation基本都有,结合RESTful规范使用能极大地减少了代码量,保证了API部分的清晰。
更多待补,英文系列教程可参考Retrofit-Retrofit Series