前面介绍了使用AIDL做为模块化开发的解耦工具,但其实Java自身的SPI(Service Provider Interface)机制也可做到,更简单,同样无需引用额外的第三方库,原生态、无公害。

基本结构

Demo的框架跟之前一样如下:

声明服务接口

在framework下新建一个接口:

interface ISayHelloService {
    fun sayHello(): String
}

实现接口功能

在module_a中,我们需要实现这个接口的具体功能:

@AutoService(ISayHelloService::class)
class SayHelloService : ISayHelloInterface {
    override fun hello(): String = "Hello, I am Module A."
}

这里使用了AutoService来进行实例的注册,当然也可以手动配置,在main目录下新建: resources/META-INFO/services/com.ezstudio.framework. ISayHelloService,内容填写:

com.ezstudio.module_a.SayHelloService

调用接口

在module_b中的activity中有个button,点击则调用前面的服务接口,将得到的结果通过toast输出,跟之前的区别是,这里使用了ServiceLoader来发现服务:

class ModuleBActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_module_b)

        call_module_a.setOnClickListener {
            val loader = ServiceLoader.load(ISayHelloService::class.java)

            loader.firstOrNull()?.sayHello()?.let {
                Toast.makeText(this@ModuleBActivity, it, Toast.LENGTH_LONG).show()
            }
        }
    }
}

ServiceLoader.load返回一个ServiceLoader,ServiceLoader实现了Iterable接口,可以遍历所有配置的服务实例。

点击按钮就能看到输出了:

总结

目前已知最简单的接口通信。相比AIDL的方式,缺点是不支持跨进程,需要在接口实现的地方自己处理。