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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值