zoukankan      html  css  js  c++  java
  • Retrofit

    Retrofit 不算是一个网络库,它应该算是封装了 okhttp ,retrofit的最大特点就是解耦,要解耦就需要大量的设计模式,然后为我们提供了一个友好的接口的一个工具库吧。

     1、创建Retrofit对象:

    builder 模式,外观模式(门面模式)

    外观模式具有高内聚、低耦合的特性,对外提供简单统一的接口,隐蔽了子系统具体的实现、隔离变化。

    在封装某些特定功能时,比如下载module,外观模式是一种很好的设计规范。即下载module与其他module通信时通过DownloadManager对象进行。Retrofit是整个库的一个入口类,Retrofit库的使用基本都是围绕着这个类。

    1 Retrofit retrofit = new Retrofit.Builder()
    2     .baseUrl("https://api.github.com/")
    3     .build();

    2、定义api

    public interface StudentApi {
    
        /**
         * 学生列表 for age
         */
        @POST("/student/studentList")
        Observable<List<Student>> selectStudentListForAge(@Field("age") int age);
    
    }

    获取 API 实例:通过动态代理模式:使用动态代理,因为对接口的所有方法的调用都会集中转发到 InvocationHandler#invoke 函数中,我们可以集中进行处理,更方便了。

    // 在请求,初始化StudentApi 
    StudentApi  mStudentApi = retrofit.create(StudentApi.class);

    调用create()方法,通过 Proxy 类静态函数生成代理对象StudentApi并返回:

      Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);  

    loader表示类加载器
    interfaces表示委托类的接口,生成代理类时需要实现这些接口
    hInvocationHandler实现类对象,负责连接代理类和委托类的中间类

    关于动态代理的详细介绍,可以查看 codeKK 公共技术点之 Java 动态代理动态代理以及利用动态代理实现servicehook

    1 // 调用其方法时,调用了Retrofit的动态代理的InvocationHandler对象MethodHandler对象
    2  mStudentApi.selectStudentListForAge(18)....;

    执行该方法后,调用了InvocationHandler对象的invoke方法。

    在invoke方法上,处理并返回一个http请求对象,在此,还可以做些有用的操作,例如统计执行时间、进行初始化和清理、对接口调用进行检查等。

    1 // 调用代理对象的每个函数实际最终都是调用了InvocationHandler的invoke函数
    2 @Override
    3 public Object invoke(Object proxy, Method method, Object[] args)

    proxy 通过 Proxy.newProxyInstance() 生成的代理类对象。
    method 表示代理对象被调用的函数。
    args 表示代理对象被调用的函数的参数。

    1、当执行subscribe的时候,整个http请求执行。

    2、调用

    mStudentApi.selectStudentListForAge(18)

    返回对象的execute()enqueue(Callback<T> callback)方法,就能发送一个Http请求了:

     1 mStudentApi.selectStudentListForAge(18)
     2 .observeOn(AndroidSchedulers.mainThread())
     3                 .subscribe(new Subscriber<List<Student>>() {
     4                     @Override
     5                     public void onCompleted() {
     6 
     7                     }
     8 
     9                     @Override
    10                     public void onError(Throwable e) {
    11                         
    12                     }
    13 
    14                     @Override
    15                     public void onNext(List<Student> studentList) {
    16                          
    17                     }
    18                 }));

     熟练使用annotation、reflect,造一个retrofit雏形。

    定义post、get、field等:

     1 import java.lang.annotation.Documented;
     2 import java.lang.annotation.Retention;
     3 import java.lang.annotation.Target;
     4 import static java.lang.annotation.ElementType.METHOD;
     5 import static java.lang.annotation.RetentionPolicy.RUNTIME;
     6 
     7 @Documented
     8 @Target(METHOD)
     9 @Retention(RUNTIME)
    10 public @interface POST {
    11     String value() default "";
    12 
    13     boolean requestSync() default false;
    14 }
    POST
     1 import java.lang.annotation.Documented;
     2 import java.lang.annotation.Retention;
     3 import java.lang.annotation.Target;
     4 import static java.lang.annotation.ElementType.METHOD;
     5 import static java.lang.annotation.RetentionPolicy.RUNTIME;
     6 
     7 @Documented
     8 @Target(METHOD)
     9 @Retention(RUNTIME)
    10 public @interface GET {
    11     String value() default "";
    12 }
    GET
     1 import java.lang.annotation.Documented;
     2 import java.lang.annotation.Retention;
     3 import java.lang.annotation.Target;
     4 import static java.lang.annotation.ElementType.PARAMETER;
     5 import static java.lang.annotation.RetentionPolicy.RUNTIME;
     6 
     7 @Documented
     8 @Target(PARAMETER)
     9 @Retention(RUNTIME)
    10 public @interface Field {
    11     String value();
    12 
    13     boolean encoded() default false;
    14 }
    Field

    创建BaseRetrofit对象,作为基类,其子类继承并重写createApi方法,在方法中,创建并配置retrofit对象。

     1 import java.util.Map;
     2 import java.util.concurrent.ConcurrentHashMap;
     3 
     4 public abstract class BaseRetrofit {
     5 
     6         // http请求
     7     SimpleRepository repository;
     8 
     9     public <T> T create(Class<T> clazz) {
    10                // 可做缓存对象操作
    11         T t = createApi(clazz);
    12         return t;
    13     }
    14 
    15     protected abstract <T> T createApi(Class<T> clazz);
    16 
    17     protected RepositoryProxy.Builder getProxyBuilder(){
    18         return new RepositoryProxy.Builder(){
    19             @Override
    20             public RepositoryProxy build() {
    21                 RepositoryProxy proxy = super.build();
    22 
    23                 setRepository(proxy.getRepository());
    24 
    25                 return proxy;
    26             }
    27         };
    28     }
    29 
    30         protected void setRepository(SimpleRepository repository) {
    31         this.repository = repository;
    32     }
    33 
    34     public SimpleRepository getRepository() {
    35         return repository;
    36     }
    37 
    38

    创建子类:使用时,new StudentRetrofit().create(StudentApi.class);生成动态代理类,通过RepositoryProxy 代理操作。

     1 public class StudentRetrofit extends BaseRetrofit {
     2 
     3     @Override
     4     protected  <T> T createApi(Class<T> clazz) {
     5         RepositoryProxy retrofit = getProxyBuilder().baseurl("http://www.baidu.com")
     6                                                     .build();
     7 
     8         return retrofit.create(clazz);
     9     }
    10 }

    RepositoryProxy 代理操作:

     1 public class RepositoryProxy {
    2 public <T> T create(Class<T> clazz) { 3 if (!clazz.isInterface()) { 4 throw new RuntimeException("retrofit Service not interface"); 5 } 6 7 return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, new ApiProxy(this)); 8 } 9 10

    InvocationHandler对象:

     1 public class ApiProxy implements InvocationHandler {
     2 
     3 @Override
     4     public Object invoke(Object proxy, Method method, Object... args) throws Throwable {
     5 
     6         // If the method is a method from Object then defer to normal invocation.
     7         if (method.getDeclaringClass() == Object.class) {
     8             return method.invoke(this, args);
     9         }
    10         
    11         // 返回http请求对象
    12         return post(method, args);
    13     }
    14 
    15

    附录

    retrofit官方文档
    用 Retrofit 2 简化 HTTP 请求
    使用Retrofit请求API数据
    Retrofit2 更新指南
    RESTful API 设计指南

    Android Retrofit 2.0使用

    Android Retrofit 2.0 使用-补充篇

    Retrofit源码设计模式解析上

    Retrofit源码设计模式解析下

    使用Retrofit请求API数据-codepath教程

    Retrofit源码解析

    Retrofit 源码的一个分析与导读

  • 相关阅读:
    <Redis开发与运维> 阅读笔记
    请求行,请求头,请求体详解
    char 与 varchar 的区别
    python字符串的常用方法。
    快速排序的代码及原理
    C#之Dictionary源码
    C#中构造函数
    U3D——单例模式的用法
    U3D学习——设置VS2019作为开发工具
    U3D学习——脚本运行周期
  • 原文地址:https://www.cnblogs.com/CharlesGrant/p/5803846.html
Copyright © 2011-2022 走看看