先介绍下框架 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就会自动生成代理对象