先介绍下框架 actor-kotlin(http://github.com/xuehuiniaoyu/actor-kotlin) 还有一个Android Demo

(https://github.com/xuehuiniaoyu/actor-demo)

actor-kotlin是kotlin开发的动态代理框架,能够实现两个不同对象实现函数模仿。

举个栗子:

宿主模块有一个类 class ApiKit {

        fun callApi(key: String, callback: (apiResponse: ApiResponse)) {

                ...

                callback(response)

        }

}

组件1 想要使用宿主的ApiKit实现网络请求,于是就会定义一个接口,接口的方法就模拟ApiKit 如下:

interface ApiKitProxy {

        fun callApi(key: String, callback: (apiResponse: Any)) // 因为组件没有宿主的对象,所以只能用Any代替

}

接下来就可以通过Actor代理这个ApiKitProxy并实现调用ApiKit的方法

val apiKit: Any = ActorBean(applicationContext).get("apiKit") ?: error("")

val apiKitProxy = Actor(apiKit).imitate(APIKitProxy::class.java)

apiKitProxy.callApi("api1") { resp ->

        Log.i(TAG, "resposne $resp")

}

这样就就可以传值成功调用并传值回来

说明:ActorBean是对象赋值取值工具,通过name直接操作属性,也可以把get set方法转交给接口实现

接下来,如果更复杂的场景,宿主方法接受的参数是一个接口呢?

interface APIContract {
    fun getApiKey(): String
    fun onSuccess(response: APIResponse)
    fun onFail()
}
class APIKit {
    fun callApi(apiKey: String, contract: APIContract) {
        println("apiKey: $apiKey")
        val key = contract.getApiKey()
        val url = APIDeclaration[key]
        GlobalScope.launch(Dispatchers.IO) {
            val response = call(url ?: error("$key isNot defined!"))
            launch(Dispatchers.Main) {
                if(response.code == 200)
                    contract.onSuccess(response)
                else
                    contract.onFail()
            }
        }
    }

    private fun call(url: String): APIResponse {
        return try {
            val client = OkHttpClient()
            val request = Request.Builder().url(url).build()
            val response = client.newCall(request).execute()
            val data = response.body?.string()
            APIResponse(response.code, data)
        } catch (e: Exception) {
            APIResponse(-1, null)
        }
    }
}

组件代码:

interface APIKitProxy {
    fun callApi(key: String, @DynamicImplementation contract: Any)
}

interface APIContractProxy {
    fun getApiKey(): String
    fun onSuccess(response: Any)
    fun onFail()
}
apiKit.callApi("data", object: APIContractProxy {
    override fun getApiKey(): String = "api1"

    override fun onSuccess(response: Any) {
        val data = ActorBean(response).get<String>("data")
        findViewById<TextView>(R.id.txtData).text = data
    }

    override fun onFail() {
        findViewById<TextView>(R.id.txtData).text = "api call fail"
    }
})

给参数对象上加@DynamicImplementation就会自动生成代理对象

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐