我正在使用依赖注入为活动提供全局对象(@Singleton
)和非全局对象(@ActivityScoped
)。
现在我想知道我是否做得对,如果可以做得更好。 DI实现中最有趣的部分是将对象SomeManager
注入到具有受限范围的2个不同活动中
这是代码
主要应用组件
@Singleton
@Component(modules = [
ApplicationModule::class,
AndroidSupportInjectionModule::class,
ActivityModule::class,
ManagerModule::class,
...
ClientModule::class])
interface AppComponent : AndroidInjector<App> {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): AppComponent.Builder
fun build(): AppComponent
}
}
应用程序模块
@Module
abstract class ApplicationModule {
@Binds
@Singleton
internal abstract fun bindContext(application: Application): Context
}
活动模块
@Module
abstract class ActivityModule {
@ActivityScoped
@ContributesAndroidInjector(modules = [MainActivityModule::class])
internal abstract fun mainActivity(): MainActivity
@ActivityScoped
@ContributesAndroidInjector(modules = [LoginActivityModule::class])
internal abstract fun loginActivity(): LoginActivity
}
现在我想向SomeManager
注入一个新的LoginActivity
,为MainActivity
注入一个新的@ContributesAndroidInjector(modules...
。
该方法为每个活动设置了一个模块,就像您在@Module
object MainActivityModule {
@JvmStatic
@Provides
@ActivityScoped
internal fun provideSomeManager(activity: MainActivity, apiClient: ApiClient) =
SomeManager(activity, apiClient)
}
注释中看到的那样。这两个文件的实现看起来像这样
@Module
object LoginActivityModule {
@JvmStatic
@Provides
@ActivityScoped
internal fun provideSomeManager(activity: LoginActivity, apiClient: ApiClient) =
SomeManager(activity, apiClient)
}
和
LoginActivityModule
问题:
1)现在MainActivityModule
和SomeManager
看起来非常相似。是否有更好的方法为这两项活动提供@Singleton
而不制作SomeManager
而没有为每项活动创建模块(因为Activity
只需要Activity
,而不是特殊sublcass)?我有一些想法,只需要XXXActivity
而不是特定的XXXActivity
。 但我如何告诉匕首提供Activity
MainActivity
2)除了1)中的优化之外,这是一个正确的实现吗?
我通过以下实现解决了这个问题。 这是正确的方法吗?
将Activity
提供为@Module
object MainActivityModule {
@JvmStatic
@Provides
@ActivityScoped
internal fun provideAsActivity(activity: MainActivity): Activity = activity
}
MainActivity
将Activity
提供为@Module
object LoginActivityModule {
@JvmStatic
@Provides
@ActivityScoped
internal fun provideAsActivity(activity: LoginActivity): Activity = activity
}
@ActivityScoped
仅@Module
object ManagerModule2 {
@JvmStatic
@Provides
@ActivityScoped
internal fun provideSomeManager(activity: Activity, apiClient: ApiClient) =
SomeManager(activity, apiClient)
}
@Module
abstract class ActivityModule {
@ActivityScoped
@ContributesAndroidInjector(modules = [ManagerModule2::class, MainActivityModule::class])
internal abstract fun mainActivity(): MainActivity
@ActivityScoped
@ContributesAndroidInjector(modules = [ManagerModule2::class, LoginActivityModule::class])
internal abstract fun loginActivity(): LoginActivity
}
用于活动的Android注入器
1) Error in data.frame(..., check.names = FALSE) :
arguments imply differing number of rows: 1, 2, 0
and
2) Warning message:
In mean.default(sapply(e, function(x) { :
argument is not numeric or logical: returning NA
答案 0 :(得分:3)
现在
LoginActivityModule
和MainActivityModule
看起来非常相似。有没有更好的方法为这两项活动提供SomeManager
而不制作@Singleton
?我有一些想法,只需要Activity
而不是特定的XXXActivity
。
是的,你可以这样做。您可以替换特定活动的依赖关系,并将其替换为Activity
或Context
(取决于您的实际需要),并将该声明移动到一个单独的模块中,您可以将其包含在两个ActivityModule中。
@Module
object SomeManagerModule {
@JvmStatic
@Provides
@ActivityScoped
internal fun provideSomeManager(activity: Activity, apiClient: ApiClient) =
SomeManager(activity, apiClient)
}
要么将其包含在模块中,要么将其添加到ContributesAndroidInjector
。
@Module(includes = [SomeManagerModule::class])
object MainActivityModule { /* ... */ }
// or
@ActivityScoped
@ContributesAndroidInjector(modules = [LoginActivityModule::class, SomeManagerModule::class])
internal abstract fun loginActivity(): LoginActivity
您甚至可以通过使用构造函数注入来完全删除对模块的需求。
@ActivityScoped
SomeManager @Inject constructor(activity: Activity, apiClient: ApiClient)
无论哪种方式,您都必须将xxxActivity
绑定/提供为某个Activity
,以便Dagger可以找到它们。
除了1)中的优化之外,这是一个正确的实现吗?
对我来说很好看。你说每个Activity都需要一个新的经理,所以@ActivityScoped
似乎是正确的选择。如果您不必确保每个活动范围的组件只有一个,那么您可以完全删除范围,但这取决于您的确切用例。