Retrofit
Retrofit2:一个网络请求的适配器,将一个基本的Java接口通过动态代理的方式翻译成一个HTTP请求,并通过OkHttp去发送请求。此外它还具有强大的可扩展性,支持各种格式转换以及RxJava。
简单例子:
- 创建个请求的api接口,通过注解方式进行接口请求
1 | public interface PersonalProtocol{ |
@FormUrlEncoded
注解表示Form表单,另外还有@Multipart
等注解,如果接口不需要传递参数,那么@FormUrlEncoded
以及@Multipart
需要去掉,具体原因后面章节会讲到。@POST
表示post请求,此外还可以使用@GET
请求
- 使用Retrofit来请求数据
1 | private void requestRetrofit(){ |
上面例子的Retrofit对象还可以指定OkHttpClient等设置
1 | OkHttpClient okHttpClient = new OkHttpClient(); |
与RxJava配合使用
1 | public interface PersonalProtocol { |
1 | private void requestRetrofit(){ |
完整例子
1 | //app\build.gradle |
1 | //AndroidManifest.xml |
- 创建公共常量类
1 | public class Constants { |
- 创建首页的几个实体类
1 | public class HomeArticleEntity implements Serializable { |
1 | public class HomeArticleDetail implements Serializable { |
1 | public class ArticleData implements Serializable { |
- 网络
1 | /** |
- Activity中使用
1 | public class MainActivity extends AppCompatActivity { |
Retrofit(hencoder)
Retrofit使用方法简介
创建一个interface作为Web Service的请求稽核,在里面用注解(Annotation)写入需要配置的请求方法
1
2
3
4public interface GitHubService{
Call<List<Repo>> listRepos(; String user)
}在正式代码里用
Retrofit
创建出 interface 的实例1
2
3
4Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);调用创建出的 Service 实例的对应方法,创建出相应的可以用来发起网络请求的
Call
对象1
Call<List<Repo>> repos = service.listRepos("octocat");
使用
Call.execute()
或者Call.enqueue()
来发起请求1
repos.enqueue(callback);
Retrofit源码结构总结
通过
Retrofit.create(Class)
方法创建出 Service interface 的实例,从而使得 Service 中配置的方法变得可用,这是 Retrofit 代码结构得核心;Retrofit.create()
方法内部,使用的是Proxy.newProxyInstance()
方法来创建 Service 实例。这个方法会为参数中的多个 interface (具体到 Retrofit 来说,是固定传入一个 interface )创建一个对象,这个对象实现了所有 interface 的每个方法,并且每个方法的实现都是雷同的:调用对象实例内部的一个InvocationHandler
成员变量的invoke()
方法,并把自己的方法信息传递进去。这样就在实质上实现了代理逻辑:interface 中的方法全部由一个另外设定的InvocationHandler
对象来进行代理操作。并且,这些方法的具体实现是在运行时生成 interface 实例时才确定的,而不是在编译时(虽然在编译时就已经可以通过代码逻辑推断出来)。这就是网上所说的 “动态代理机制” 的具体含义。因此,
invoke()
方法中的逻辑,就是 Retrofit 创建 Service 实例的关键。这个方法内有三行关键代码,共同组成了具体逻辑:ServiceMethod
的创建:1
ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object,Object>) loadServiceMethod(method);
这行代码负责读取 interface 中原方法的信息(包括返回值类型、方法注解、参数类型、参数注解),并将这些信息做初步分析。
OkHttpCall
的创建:1
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
OkHttpCall
是retrofit2.Call
的子类。这行代码负责将 ServiceMethod 封装进一个retrofit2.Call
对象;而这个对象可以在需要的时候(例如它的enqueue()
方法被调用的时候,利用 ServiceMethod 中包含的信息来创建一个okhttp3.Call
对象,并调用这个okhttp3.Call
对象来进行网络请求的发起,然后对结构进行预处理(如类型转换)。adapt()
方法:1
return serviceMethod.adapt(okHttpCall);
这个方法会使用 ServiceMethod 中的 callAdapter 对象来把 okHttpCall 对象进行转换,生成一个新的
retrofit2.Call
对象,在这个新的Call
对象中,后台线程发起的请求,会在相应返回后,从主线程中调用回调方法,实现线程的自动切换。另外,这个方法不止可以生成新的
retrofit2.Call
对象,也可以生成别的类型对象,例如 RxJava 的Obervable
,来让 Retrofit 可以和 RxJava 结合使用。
思考:
Retrofit的请求和返回是如何关联的?即如何确保回调到正确的位置?
答:
1
ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object,Object>) loadServiceMethod(method);
这句话里面绑定了method与对象