美文网首页
仿Retrofit,探寻动态代理Retrofit中的应用

仿Retrofit,探寻动态代理Retrofit中的应用

作者: 言吾許 | 来源:发表于2019-08-20 15:45 被阅读0次

    最近看到有人问Retrofit的原理,然后就研究了一下,发现内部是用java的动态代理实现的,真的很巧妙,动态代理在android端的应用场景不多,retrofit算是一个,就想着能不能自己写一个简化版的Retrofit。

    只拿get做演示

    定义GET注解:

    @Documented
    @Target(METHOD)
    @Retention(RUNTIME)
    public @interface GET {
        String value() default "";
    }
    

    定义接口:

    interface ServiceApi {
        /**
         * 获取公众号列表
         * 基于 玩android开放api
         */
        @GET("/wxarticle/chapters/json")
        fun getPublicList():Call
    }
    

    核心retrofit类,利用建造者模式:

    @Suppress("UNCHECKED_CAST")
    class Retrofit(var callFactory: Call.Factory, var baseUrl: String) {
    
    
        fun <T> create(service: Class<T>): T {
            return Proxy.newProxyInstance(
                service.classLoader, arrayOf(service)
            ) { _, method, _ ->
                //解析注解
                val annotations = method.annotations
                if (annotations.isEmpty()) {
                    throw IllegalStateException("annotation required.")
                }
                annotations.forEach {
                    Logger.d(it.toString())
                    Logger.d(it is GET)
                    return@newProxyInstance when (it) {
                        is GET -> {
                            handlerGet(it.value)
                        }
                        is POST -> {
                            //不处理,只模拟GET
                        }
                        else -> {
    
                        }
                    }
                }
            } as T
        }
    
        /**
         * 处理get请求
         */
        private fun handlerGet(url: String): Call {
            val request = Request.Builder()
                .url(baseUrl + url)
                .get()
                .build()
            //这里没有做返回类型转换,默认都返回call
            return callFactory.newCall(request)
        }
    
    
        class Builder {
            private var baseUrl: String? = null
            private var callFactory: Call.Factory? = null
            /**
             * 模拟传入baseUrl
             */
            fun baseUrl(baseUrl: String): Builder {
                this.baseUrl = baseUrl
                return this
            }
    
            /**
             * 模拟传入client
             */
            fun client(client: OkHttpClient): Builder {
                this.callFactory = client
                return this
            }
    
            fun build(): Retrofit {
                if (baseUrl == null) {
                    throw IllegalStateException("Base URL required.")
                }
                if (callFactory == null) {
                    callFactory = OkHttpClient()
                }
                return Retrofit(callFactory!!, baseUrl!!)
            }
        }
    }
    

    使用:

     //初始化retrofit
            val api = Retrofit
                .Builder()
                .baseUrl("https://wanandroid.com")
                .client(OkHttpClient())
                .build()
                .create(ServiceApi::class.java)
    
            //按钮点击(这里利用kotlin的扩展函数,做的防重点)
            bt_net.singleClick {
                api.getPublicList()
                    .enqueue(object : Callback {
                        override fun onFailure(call: Call, e: IOException) {
                            Logger.d(e.message)
                        }
    
                        override fun onResponse(call: Call, response: Response) {
                            val res = response.body()?.source()?.readUtf8()
                            Logger.d(res)
                        }
                    })
            }
    

    返回结果:

    {
        "data": [{
            "children": [],
            "courseId": 13,
            "id": 408,
            "name": "鸿洋",
            "order": 190000,
            "parentChapterId": 407,
            "userControlSetTop": false,
            "visible": 1
        }, {
            "children": [],
            "courseId": 13,
            "id": 409,
            "name": "郭霖",
            "order": 190001,
            "parentChapterId": 407,
            "userControlSetTop": false,
            "visible": 1
        }, {
            "children": [],
            "courseId": 13,
            "id": 410,
            "name": "玉刚说",
            "order": 190002,
            "parentChapterId": 407,
            "userControlSetTop": false,
            "visible": 1
        }, {
            "children": [],
            "courseId": 13,
            "id": 411,
            "name": "承香墨影",
            "order": 190003,
            "parentChapterId": 407,
            "userControlSetTop": false,
            "visible": 1
        }, {
            "children": [],
            "courseId": 13,
            "id": 413,
            "name": "Android群英传",
            "order": 190004,
            "parentChapterId": 407,
            "userControlSetTop": false,
            "visible": 1
        }, {
            "children": [],
            "courseId": 13,
            "id": 414,
            "name": "code小生",
            "order": 190005,
            "parentChapterId": 407,
            "userControlSetTop": false,
            "visible": 1
        }, {
            "children": [],
            "courseId": 13,
            "id": 415,
            "name": "谷歌开发者",
            "order": 190006,
            "parentChapterId": 407,
            "userControlSetTop": false,
            "visible": 1
        }, {
            "children": [],
            "courseId": 13,
            "id": 416,
            "name": "奇卓社",
            "order": 190007,
            "parentChapterId": 407,
            "userControlSetTop": false,
            "visible": 1
        }, {
            "children": [],
            "courseId": 13,
            "id": 417,
            "name": "美团技术团队",
            "order": 190008,
            "parentChapterId": 407,
            "userControlSetTop": false,
            "visible": 1
        }, {
            "children": [],
            "courseId": 13,
            "id": 420,
            "name": "GcsSloop",
            "order": 190009,
            "parentChapterId": 407,
            "userControlSetTop": false,
            "visible": 1
        }, {
            "children": [],
            "courseId": 13,
            "id": 421,
            "name": "互联网侦察",
            "order": 190010,
            "parentChapterId": 407,
            "userControlSetTop": false,
            "visible": 1
        }, {
            "children": [],
            "courseId": 13,
            "id": 427,
            "name": "susion随心",
            "order": 190011,
            "parentChapterId": 407,
            "userControlSetTop": false,
            "visible": 1
        }, {
            "children": [],
            "courseId": 13,
            "id": 428,
            "name": "程序亦非猿",
            "order": 190012,
            "parentChapterId": 407,
            "userControlSetTop": false,
            "visible": 1
        }, {
            "children": [],
            "courseId": 13,
            "id": 434,
            "name": "Android达摩院",
            "order": 190013,
            "parentChapterId": 407,
            "userControlSetTop": false,
            "visible": 1
        }],
        "errorCode": 0,
        "errorMsg": ""
    }
    

    只是一个简单的模拟,很多深入的功能如果有时间的话再完善~
    github传送门

    完工 撒花~

    相关文章

      网友评论

          本文标题:仿Retrofit,探寻动态代理Retrofit中的应用

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