美文网首页
十、Retrofit简析

十、Retrofit简析

作者: 小鱼你好 | 来源:发表于2022-10-11 21:34 被阅读0次

    Retrofit注解分为三类

    请求方法注解:GET、POST、PUT、DELETE、 HEAD、PATCH、OPTIONS和HTTP
    标记类注解:FormUrlEncoded标记表单请求、Multipart标记上传文件请求、Streaming代表响应数据已流的形式返回,如果不设置则会默认把全部数据加载到内存,所以下载大文件时需要使用。
    参数类注解:Header、Headers、Body、Path、Field、FieldMap、Part、PartMap、Query、QueryMap

    对于GET请求

    @Path动态配置接口地址
    @Query动态更换请求参数
    @QueryMap设置一组动态参数

    public interface IpService{
        @GET("getIpInfo.pho?ip=59.108.54.37")//定义请求方法和请求接口
        Call<IpModel> getIpMsg()//定义返回类型参数
    }
    String url = "http://www.baidu.com/"
    Retrofit retrofit = new Retrofit.Builder()
                               .baseUrl(url)
                               .addConverterFactory(GsonConverterFactory.create())//设置返回值Json支持
                               .bulid()
    IpServer ipServer = retrofit.create(IpServer.class)
    Call<IpModel> call = ipServer.getIpMsg()
    call.enqueue(new Callback<IpModel>(){
        public void onResponse(Call<IpModel> call,Response<IpModel> response)
        public void onFailure()
    })
    

    中断请求可以调用call.cancel()方法。

    对POST请求

    @FormUrlEncoded标记请求为表单请求
    @Field用于设置请求参数
    @Body传输数据类型JSON,传入对应对象会自动转成字符串进行传输
    @Part单个文件上传,需要加上标记@Multipart表示允许多个@Part。
    @PartMap多个文件上传,也需要加上标记@Multipart

    @Header用于添加header

    源码分析

    构建Retrofit使用的Builder,其构造函数内部调用了Platform.get()方法,调用了findPlatform()方法其内部判断根据不同的平台构建不同的线程池。
    在Builder.build()方法中返回Retrofit实例,方法中首先判断baseUrl是否设置,如未设置抛出异常,接下来获取默认的Call.Factory即为构建Retrofit时调用callFactoty方法传入的对象并利用它的OkhttpClient对象,没有设置callFactory时会新创建OkhttpClient,build方法中还会利用callbackExector = platform.defaultCallbackExecutor()安卓中利用handler将回调切换到UI线程。接下来利用adapterFactories将Call进行对象转化。

    Call的创建过程

    IpServer ipServer = retrofit.create(IpServer.class)
    Call<IPModel> call = ipServer.getIpMsg()
    在create方法中返回一个Proxy.newProxyInstance动态代理对象,当调用getIpMsg()方法获取Call对象时调用的是InvocationHandler(Proxy.newProxyInstance构建时传入的匿名对象)的invoke方法,拿到Call其实是ExecutorCallbackCall,其是对Call的封装。invoke方法中还获取到了ServiceMethod
    serviceMethod = loadServiceMethod(method)//method即为定义的getIpMsg()方法,在此方法中会先从InvocationHandler中的serviceMethodCache查询是否有缓存,有直接使用,没有创建一个ServiceMethod并加入serviceMethodCache中缓存起来。ServiceMethod是通过调用其Buidler的build方法构建的,查看build方法内部调用了createCallAdapter方法,即创建Retrofit时传入的adapterFactories添加对象的get方法,同时会默认添加defaultCallAdapterFactory即ExecutorCallAdapterFactory,从其get方法中得到CallAdapter对象,CallAdapter的responseType方法会返回数据的真实类型,adapt 方法会创建ExecutorCallbackCall,它会将call 的回调转发至UI线程。在ServiceMethod中的build方法中在调用createResponseConverter遍历converterFactories得到合适的Converter用来转换对象,在构建Retrofit时调用了 addConverterFactory将GsonConverterFactory(Converter.Factory的子类)添加到converterFactories列表中表示返回数据类型为Json对象。接着利用parseMethodAnnotation方法对请求方式和地址进行解析,然后解析请求参数最后构建return new ServiceMethod<>(this)。ServiceMethod类主要用于处理构建Retrofit时传入的设置,以及解析注解获取请求方法和请求参数。
    在Retrofit的create方法中即InvocationHandler的invoke方法中,在调用了loadServiceMethod方法后会创建 OkHttpCall进行赋值操作,紧接着调用 serviceMethod.callAdapter.adapt(okHttpCall)得到ExecutorCallbackCall,其是对Call的封装通过callbackExecutor将请求回调到 UI 线程。我们得到 Call 对象后会调用它的 enqueue 方法,其实调用的是ExecutorCallbackCall的enqueue方法,最终调用的是delegate的enqueue方法。 delegate是传入的OkHttpCall。OkHttpCall的enqueue方法中调用了parseRespinse方法,根据不同的状态码进行不同操作,最后T body = serviceMethod.toResponse(catchingBody)在此根据传入的GsonConverterFactory利用调用responseConverter.convert转换为特定的数据格式(JSON)。

    相关文章

      网友评论

          本文标题:十、Retrofit简析

          本文链接:https://www.haomeiwen.com/subject/aydzartx.html