Retrofit框架的封装流程以及源码分析

26 篇文章 0 订阅
26 篇文章 0 订阅

Retrofit框架的封装流程以及源码分析:


1.Retrofit框架的封装:

01.添加依赖

    //Retrofit2的相关依赖
    implementation 'com.squareup.retrofit2:retrofit:2.4.0'
    //rxjava转换器
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
    //rxjava相关依赖
    implementation 'io.reactivex.rxjava2:rxjava:2.1.1'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
    //gson转换
    implementation "com.google.code.gson:gson:2.8.5"
//    //http请求拦截器Interceptor依赖  ->  依赖无法下载
//    implementation('com.github.ihsanbal:LoggingInterceptor:3.0.0') {
//        exclude group: 'org.json', module: 'json'
//    }
    //协程依赖
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0-RC-native-mt'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0-RC-native-mt'

02.添加网络权限

//AndroidManifest.xml中设置网络权限和网络明文访问
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.imooc.retrofitdemo">

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

    //FIXME 设置可以明文访问网络
    <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/Theme.RetrofitDemo"
            android:usesCleartextTraffic="true"
            android:networkSecurityConfig="@xml/network_config">
        <activity android:name=".MainActivity"
                android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

//设置可以网络明文访问
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true" />
</network-security-config>

03.自定义观察类MyObserver

//创建一个抽象abstract的观察类,继承生命周期的Observer,泛型就是ResponseBody
//继承RxJava的观察类Observer
abstract class MyObserver: Observer<ResponseBody> {

    //请求完成了
    override fun onComplete() {

    }

    //观察者订阅了
    override fun onSubscribe(d: Disposable) {

    }

    //请求成功了
    override fun onNext(t: ResponseBody) {
        //定义一个抽象类,让子类自己去实现
        onSuccess(t.string())
    }

    //请求出错了
    override fun onError(e: Throwable) {
        if (e.message!!.contains("401") && e.message!!.contains("Unauthorized")) {
            //用户认证到期了 -> 走Session监听器接口中的方法
            //用户断网了 -> 走网络监听器接口中的方法
            CallManager.onSessionListener?.onReLogin()
            return
        }
        if (e.message != null) {
            Log.i("hy55", "e.message==${e.message}")
            if (e.message!!.contains("failed to connect to")
                || e.message!!.contains("Failed to connect to")
                || e.message!!.contains("No route to host")
                || e.message!!.contains("timeout")
                || e.message!!.contains("connect timed out")
                || e.message!!.contains("unsupported auth scheme")) {
                val am = BaseApplication.getAppContext().getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
                if (am.getRunningTasks(1).get(0)?.topActivity != null) {
                    val cn: ComponentName = am.getRunningTasks(1)?.get(0)?.topActivity!!
                    //当前不是首页
                    if (!cn.className.contains("MainActivity")) {
                        //TODO 直接退出到首页
                    }
                }
                return
            }
        }
        //子类自己实现onFailure接口方法
        onFailure(e)
    }

    //抽象abstract方法 -> 请求成功了
    abstract fun onSuccess(data: String?)

    //抽象abstract方法 —> 请求失败了
    abstract fun onFailure(e: Throwable)
}

04.封装Retrofit请求

object RetrofitClient {

    const val TAG = "RetrofitClient"

    /**
     * 设置超时时间
     */
    private const val timeOut = 30L

    /**
     * 创建单例对象,使用@JvmField注解就可以直接使用该参数retrofit,而不是使用Retrofit
     */
    @JvmField
    var retrofit: Retrofit? = null

    /**
     * 创建API单例对象:获取其中一条API请求
     * 使用@JvmField注解可以直接使用
     */
    @JvmField
    var requestApi: NewApi? = null

    fun initLogin() {
//        val httpLoggingInterceptor = LoggingInterceptor.Builder()
//            .loggable(BuildConfig.DEBUG)
//            .setLevel(Level.BODY)
//            .log(Platform.INFO)
//            .request("请求")
//            .response("响应")
//            .build()

        val client = OkHttpClient.Builder()
            .connectTimeout(5, TimeUnit.SECONDS)
            .readTimeout(5, TimeUnit.SECONDS)
            .writeTimeout(5, TimeUnit.SECONDS)
            .addInterceptor { chain -> //拿到我们的请求
                val original = chain.request()
                //重新进行build
                val builder = original.newBuilder()
                //builder立面放入请求头 || 或者放入token
                builder.addHeader("Context-Type", "application/json")
                val newRequest = builder.build()
                chain.proceed(newRequest)
            }
            .build()

        //TODO 设置服务器IP地址
        retrofit = Retrofit.Builder()
            .client(client)
            .baseUrl("http://10.1.1.1:8080/api/")
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()

        //创建请求
        if (retrofit != null) {
            requestApi = retrofit?.create(NewApi::class.java)
        }
    }

    //创建HTTP请求的API接口方法
    interface NewApi {
        //这里的Observable是Reactivex的依赖
        @POST("account/login")
        fun accountLogin(@Body body: RequestBody): Observable<ResponseBody>

        //同步请求的API
        @POST("account/login")
        fun accountSynLogin(@Body body: RequestBody): retrofit2.Call<ResponseBody>

    }

}

05.创建同步请求和异步请求

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //使用kotlin-kapt、kotlin-android-extensions可以直接绑定控件
        AsynRequestBtn.setOnClickListener {
            val loginModel = LoginModel("654321", "123456")
            val messageJson = Gson().toJson(loginModel)
            Log.i("TAG", "messageJson==$messageJson")
            RetrofitClient.let {
                it.initLogin()
                it.requestApi?.accountLogin(RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), messageJson))
                    ?.subscribeOn(Schedulers.io())
                    ?.observeOn(AndroidSchedulers.mainThread())
                    ?.subscribe(object : MyObserver() {
                        override fun onSuccess(data: String?) {
                            Log.i("TAG", "data==$data")
                            Toast.makeText(this@MainActivity, "成功了", Toast.LENGTH_SHORT).show()
                        }

                        override fun onFailure(e: Throwable) {
                            Log.i("TAG", "e==${e.message}")
                            Toast.makeText(this@MainActivity, "失败了", Toast.LENGTH_SHORT).show()
                        }
                    })

            }
        }
        //TODO: 注意1:添加network_config.xml,设置usesCleartextTraffic为true
        //TODO: 注意2:AndroidManifest.xml中添加Internet的相关Permission
        SynRequestBtn.setOnClickListener {
            //FIXME 不能在主线程中进行同步请求
            GlobalScope.launch {
                val loginModel = LoginModel("654321", "123456")
                val messageJson = Gson().toJson(loginModel)
                RetrofitClient.let {
                    //FIXME 这里的.string()才是获取Response的方法(注意:不是.toString())
                    //FIXME API请求需要换成同步请求的API(修改返回值为Call<ResponseBody>)
                    val result = it.requestApi?.accountSynLogin(RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), messageJson))
                        ?.execute()?.body()?.string()
                    Log.i("TAG", "result==$result")
                }
            }
        }

    }
}

2.Retrofit使用实例:

01.同步请求

01.注意:同步请求不能在主线程中进行
02.注意:.execute?.body()?.string()才能获取到ResponseBody的内容

            //FIXME 不能在主线程中进行同步请求
            GlobalScope.launch {
                val loginModel = LoginModel("654321", "123456")
                val messageJson = Gson().toJson(loginModel)
                RetrofitClient.let {
                    //FIXME 这里的.string()才是获取Response的方法(注意:不是.toString())
                    //FIXME API请求需要换成同步请求的API(修改返回值为Call<ResponseBody>)
                    val result = it.requestApi?.accountSynLogin(RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), messageJson))
                        ?.execute()?.body()?.string()
                    Log.i("hy55", "result==$result")
                }
            }

02.异步请求

            RetrofitClient.let {
                it.initLogin()
                it.requestApi?.accountLogin(RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), messageJson))
                    ?.subscribeOn(Schedulers.io())
                    ?.observeOn(AndroidSchedulers.mainThread())
                    ?.subscribe(object : MyObserver() {
                        override fun onSuccess(data: String?) {
                            Log.i("hy55", "data==$data")
                            Toast.makeText(this@MainActivity, "成功了", Toast.LENGTH_SHORT).show()
                        }

                        override fun onFailure(e: Throwable) {
                            Log.i("hy55", "e==${e.message}")
                            Toast.makeText(this@MainActivity, "失败了", Toast.LENGTH_SHORT).show()
                        }
                    })

            }

3.Retrofit源码分析:

01.

02.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值