Dynami c Доставка является относительно новой функцией, поэтому она имеет множество ограничений. Одно из этих ограничений заключается в том, что вы не можете получить доступ к коду и ресурсам модуля Dynami c обычным способом, поэтому он не может быть зависимостью для других модулей. В настоящее время вы можете получить доступ к модулю Dynami c с помощью отражения и иметь функции Dynami c, определенные через интерфейсы publi c в модуле общей библиотеки, и загружать их фактические реализации (расположенные в функциональных модулях Dynami c) во время выполнения с помощью 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)
}
}
И для фактического доступа к коду Dynami c Использование функции
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
}
}
Взято из здесь . Также там гораздо больше информации, поэтому я бы порекомендовал вам проверить ее.
Как правило, я просто не рекомендовал бы использовать Dynami c Feature в качестве зависимости и соответственно планировать архитектуру вашего приложения.
Надеюсь, это поможет.