Android多模块组件化开发,宿主无需实现组件接口且组件能够调用宿主方法并传值回来。
先介绍下框架 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就会自动生成代理对象
更多推荐
所有评论(0)