Retrofit的使用及原理详解


一、为什么要使用Retrofit

在Android学习过程中,网络请求是一个必学习的内容,Retrofit作为当下最热门的网络请求框架之一,由有什么优势呢?

1.OKHttp遗留下来的问题

Retrofit是对OKHttp的一层封装,本质上网络请求还是OKHttp,那么在OKHttp的基础上,Retrofit做了哪些优化,首先来看一下OKHttp遗留下来的问题

1)用户网络请求的接口配置繁琐,尤其是需要配置请求body,请求头,参数的时候;
2)数据解析过程需要用户手动拿到responsbody进行解析,不能复用;
3)无法适配自动进行线程的切换。

这些问题将在Retrofit中得到解决,接下来看看Retrofit的使用以及如何解决的这些问题


二、Retrofit的使用

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

1.引入库

	//对okhttp的支持库
	implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.2'
	//retrofit库(必须)
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    //gson支持库
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    //rxjava
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.7.2'
    //协程
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'
    //适配器
    implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'
    //okhttp拦截器
    implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2'

2.添加网络权限

<uses-permission android:name="android.permission.INTERNET"/>

3.interface

上面说到okhttp问题的第一条用户网络请求的接口配置繁琐,尤其是需要配置请求body,请求头,参数;这个问题就是在这里解决,retrofit中通过接口和注解的方式配置

通过@GET、@PUT注解可以定义HTTP的Request Method,注解中可以添加参数指定请求的path

例如:

interface GetCodeService {

    //GET,POST,Headers
    @Headers("Content-Type: application/x-www-form-urlencoded")
    @GET("auth/sendCode")
    //Path,Query,Body
    fun GetCode(@Query("phone") phone : String) : Call<GetCodeBean>

}

常用到的注解有GET,POST,Headers,Path,Query,Body

4.Retrofit封装

object RetrofitClient {

    private const val BASE_URL = "http://124.220.203.140:80/"

    /*
    构建者模式
    创建retrofit对象, 构建一个网络请求的载体对象,和okhttp构建OkhttpClient对象有一样的意义,
    只不过retrofit在build的时候有非常多的初始化内容,这些内容可以为后面网络请求提供准备,
    如准备 现成转换Executor,Gson convert,RxJavaCallAdapter
     */

    private val retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    //Retrofit的精髓,为统一配置网络请求完成动态代理的设置
    fun <T> create(serviceClass: Class<T>): T = retrofit.create(serviceClass)
}

Retrofit创建使用构建者模式

创建retrofit对象, 构建一个网络请求的载体对象,和okhttp构建OkhttpClient对象有一样的意义,只不过retrofit在build的时候有非常多的初始化内容,这些内容可以为后面网络请求提供准备,如准备 现成转换Executor,Gson convert,RxJavaCallAdapter

在其中添加gson解析器,可直接帮我们进行解析,而不需要手动解析,这解决了okhttp遗留的第二个问题

5.网络请求

codeLoginService.CodeLogin(codeBody).enqueue(object : Callback<CodeLoginBean>{
	override fun onResponse(call: Call<CodeLoginBean>, response: Response<CodeLoginBean>) {
	
	}
	override fun onFailure(call: Call<CodeLoginBean>, t: Throwable) {

    }
})

在这里自适应线程切换可直接用于渲染UI,而不用手动切换线程,接下来就看一下Retrofit的原理解析


三、retrofit原理解析

1.Retrofit创建实例详情

在这里插入图片描述
上图就是retrofit创建的过程,可以看出

baseUrl—>callFactory(拼接了接口和参数,retrofit封装okHttp的核心表现)—> callbackExecutor(线程执行者)—>platform—> MainThreadExecutor(切换到主线程)—>handler
callbackExecutor—>adapterFactories适配器通过反射方式将返回对象进行赋值为javaBean对象(不需要json转javaBean)

2.Retrofit的代理模式

retrofit的精髓就在于create是采用了动态代理,接下来我们看一下retrofit是如何使用动态代理的

//Retrofit的精髓,为统一配置网络请求完成动态代理的设置
fun <T> create(serviceClass: Class<T>): T = retrofit.create(serviceClass)
}

构建具体网络请求对象Request(service),在这个阶段要完成的任务:1)将接口中的注解翻译成对应的参数;2)确定网络请求接口的返回值response类型以及对应的转换器;3)将Okhttp的Request封装成为Retrofit的OKhttpCall。总结来说,就是根据请求service 的Interface来封装Okhttp请求Request。

动态代理的使用

在java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和这个接口可以生成JDK动态代理类和动态代理对象。这个代理对象是存在于内存中的
1、创建一个InvocationHandler对象
InvocationHandler stuHandler = new MyInvocationHandler<Person>(stu);
2、使用Proxy类的getProxyClass静态方法生成一个动态代理类
Class<?>stuProxyClass=Proxy.getProxyClass(Person.class.getClassLoader(), new Class<?>[] {Student.class});
3、获得stuProxyClass 中一个带InvocationHandler参数的构造器constructor
Constructor<?> constructor=PersonProxy.getConstructor(InvocationHandler.class);
4、通过构造器constructor来创建一个动态实例stuProxy
Person stuProxy = (Person) constructor .newInstance(stuHandler);

简化:
//创建一个与代理对象相关联的InvocationHandler
1、InvocationHandler stuHandler = new MyInvocationHandler(stu);
//创建一个代理对象stuProxy,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
2、 Person stuProxy= (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler);


四、retrofit流程总结

retrofit—>建造者—>create(动态代理)—>getPersonInfo接口(注解解析+URL拼接)到invoke方法中—>call.enqueue(丢给okHttp,realCall—>AsyncCall内部类,切到子线程)—> ExecutorCallAdapterFactory中返回数据的enqueue()方法(切回主线程callbackExecutor.execute())

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值