动态交付是相对较新的功能,因此它有很多限制。其中一个限制是您无法以常规方式访问动态模块的代码和资源,因此它不能成为其他模块的依赖项。目前,您可以通过反射访问动态模块,并通过公共库模块中的公共接口定义动态功能,并在运行时使用ServiceLoader
. 它有其性能缺点。可以使用 R8 将它们最小化,ServiceLoaderRewriter
但不能完全删除。
虽然使用反射很容易出错,但我们可以使用它来最小化它@AutoService
-AutoService
是一个注释处理器,它将扫描项目以查找带有注释的类@AutoService
,对于它找到的任何类,它都会自动为其生成一个服务定义文件。
这是如何完成的小例子
// All feature definitions extend this interface, T is the dependencies that the feature requires
interface Feature<T> {
fun getMainScreen(): Fragment
fun getLaunchIntent(context: Context): Intent
fun inject(dependencies: T)
}
interface VideoFeature : Feature<VideoFeature.Dependencies> {
interface Dependencies {
val okHttpClient: OkHttpClient
val context: Context
val handler: Handler
val backgroundDispatcher: CoroutineDispatcher
}
}
internal var videoComponent: VideoComponent? = null
private set
@AutoService(VideoFeature::class)
class VideoFeatureImpl : VideoFeature {
override fun getLaunchIntent(context: Context): Intent = Intent(context, VideoActivity::class.java)
override fun getMainScreen(): Fragment = createVideoFragment()
override fun inject(dependencies: VideoFeature.Dependencies) {
if (videoComponent != null) {
return
}
videoComponent = DaggerVideoComponent.factory()
.create(dependencies, this)
}
}
并实际访问动态功能使用的代码
inline fun <reified T : Feature<D>, D> FeatureManager.getFeature(
dependencies: D
): T? {
return if (isFeatureInstalled<T>()) {
val serviceIterator = ServiceLoader.load(
T::class.java,
T::class.java.classLoader
).iterator()
if (serviceIterator.hasNext()) {
val feature = serviceIterator.next()
feature.apply { inject(dependencies) }
} else {
null
}
} else {
null
}
}
取自这里。那里还有更多信息,所以我建议您检查一下。
一般来说,我只是不建议使用动态功能作为依赖项并相应地规划您的应用程序架构。
希望能帮助到你。