使用 HILT 注入摘要 class(基础 activity)
Inject abstract class (base activity) with HILT
我刚刚开始尝试在我非常简单的项目中使用 Hilt。现在一切都在 Dagger2 上,但我想迁移到 Hilt。
我有一个 activity :
@AndroidEntryPoint
class MainActivity : BaseActivity() {
// SOME STUFF
}
还有像这样的 BaseActivity :
abstract class BaseActivity : AppCompatActivity() {
// SOME STUFF
}
此外,我有一个 class 使用 baseActivity 来显示对话框。例如:
@FragmentScoped
class TestComponentImpl @Inject constructor(
private val baseActivity: BaseActivity
) : TestComponent {
override fun displayDialog() {
MaterialDialog(baseActivity).show { ...
}
}
但是,当我尝试编译时,出现了这个错误:
BaseActivity cannot be provided without an @Provides-annotated method.
所以,我的问题是:如何构造函数注入抽象 class。我尝试了很多东西但没有成功,比如在 Hilt 模块中:
@Provides
@Singleton
fun provideBaseActivity(): BaseActivity{
return BaseActivity() // Of course, it can't work cause it's an abstract class
}
或者(就像我对 Dagger 所做的那样):
@Provides
@PerActivity
fun appCompatActivity(baseActivity: BaseActivity) = baseActivity as AppCompatActivity
此外,我只是 Hilt 的初学者,所以,也许我错过了什么。我会继续搜索:)
感谢您的宝贵时间和回答:)
编辑:
我自己搜索了几天,这似乎有效,但似乎不太好...
@Singleton
@Provides
fun provideBaseActivity(baseActivity: BaseActivity): AppCompatActivity {
return baseActivity
}
但前提是我像这样放置我的 baseActivity :
open class BaseActivity Inject constructor() : AppCompatActivity()
但是,在那之后,如果我尝试像这样在我的 TestComponentImpl 中使用注入的 baseActivity(就像我在 Hilt 之前使用 Dagger 所做的那样):
override fun displayError() {
Snackbar.make(
baseActivity.findViewById(android.R.id.content),
"My error text",
Snackbar.LENGTH_LONG
).apply {
show()
}
我遇到另一个错误:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
所以我不认为我的 baseActivity 注入做得很好。我会继续调查 ;)
有点hacky(type-casting)但应该可以用(未经测试,记下我的头顶所以随时让我知道如果某些东西没有按预期工作):
创建这样的 Module
:
@Module
@InstallIn(ActivityComponent::class)
object BaseActivityModule {
@Provides
fun provideBaseActivity(activity: Activity): BaseActivity {
check(activity is BaseActivity) { "Every Activity is expected to extend BaseActivity" }
return activity as BaseActivity
}
}
最后一个演员as BaseActivity
可能是不必要的。 Kotlin 编译器应该处理这个问题。
@Boysteuf
@Bartek Lipinski
遇到以下错误:
error: [Dagger/MissingBinding] android.app.Activity cannot be provided without an @Inject constructor or an @Provides-annotated method.
public abstract static class SingletonC implements EzeApp_GeneratedInjector,
^
android.app.Activity is injected at
com.ezetap.consumerpaymentsdk.di.module.BaseActivityModule.provideBaseActivity(activity)
com.ezetap.consumerpaymentsdk.base.BaseSDKActivity is injected at
com.ezetap.consumerpaymentsdk.di.module.AppModule.provideServicePresenterPresenter(baseSDKActivity, …)
com.ezetap.consumerpaymentsdk.presenters.ServicePresenter is injected at
com.ezetap.consumerpaymentsdk.activity.ServiceSDKActivity.presenter
com.ezetap.consumerpaymentsdk.activity.ServiceSDKActivity is injected at
com.ezetap.consumerpaymentsdk.activity.ServiceSDKActivity_GeneratedInjector.injectServiceSDKActivity(com.ezetap.consumerpaymentsdk.activity.ServiceSDKActivity) [com.ezetap.consumerpaymentsdk.base.EzeApp_HiltComponents.SingletonC → com.ezetap.consumerpaymentsdk.base.EzeApp_HiltComponents.ActivityRetainedC → com.ezetap.consumerpaymentsdk.base.EzeApp_HiltComponents.ActivityC]
The following other entry points also depend on it:
com.ezetap.consumerpaymentsdk.activity.SimActivity_GeneratedInjector.injectSimActivity(com.ezetap.consumerpaymentsdk.activity.SimActivity) [com.ezetap.consumerpaymentsdk.base.EzeApp_HiltComponents.SingletonC → com.ezetap.consumerpaymentsdk.base.EzeApp_HiltComponents.ActivityRetainedC → com.ezetap.consumerpaymentsdk.base.EzeApp_HiltComponents.ActivityC]
AppModule
@Module(includes = [NetworkModule::class , BaseActivityModule::class ])
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun provideBasePresenter(baseSDKActivity: BaseSDKActivity ,ezeApi: EzeApi, @ApplicationContext context: Context ) : BaseSDKPresenter {
return BaseSDKPresenter(baseSDKActivity, ezeApi , context )
}
@Provides
@Singleton
fun provideSimPresenter(baseSDKActivity: BaseSDKActivity, ezeApi: EzeApi , @ApplicationContext context: Context ) : SimPresenter {
return SimPresenter(baseSDKActivity , ezeApi , context)
}
@Provides
@Singleton
fun provideServicePresenterPresenter(baseSDKActivity: BaseSDKActivity,ezeApi: EzeApi , @ApplicationContext context: Context ) : ServicePresenter {
return ServicePresenter(baseSDKActivity , ezeApi , context)
}
}
BaseActivityModule
@Module
@InstallIn(ActivityComponent::class)
object BaseActivityModule {
@Provides
fun provideBaseActivity(activity :Activity): BaseSDKActivity {
check(activity is BaseSDKActivity) { "Every Activity is expected to extend BaseActivity" }
return activity as BaseSDKActivity
}
}
BaseSDKActivity
open class BaseSDKActivity @Inject constructor() : AppCompatActivity() {
}
BaseSDKPresenter
@ActivityScoped
open class BaseSDKPresenter @Inject constructor(private val baseSDKActivity: BaseSDKActivity , private val ezeApi: EzeApi ,
private val context: Context )
我刚刚开始尝试在我非常简单的项目中使用 Hilt。现在一切都在 Dagger2 上,但我想迁移到 Hilt。
我有一个 activity :
@AndroidEntryPoint
class MainActivity : BaseActivity() {
// SOME STUFF
}
还有像这样的 BaseActivity :
abstract class BaseActivity : AppCompatActivity() {
// SOME STUFF
}
此外,我有一个 class 使用 baseActivity 来显示对话框。例如:
@FragmentScoped
class TestComponentImpl @Inject constructor(
private val baseActivity: BaseActivity
) : TestComponent {
override fun displayDialog() {
MaterialDialog(baseActivity).show { ...
}
}
但是,当我尝试编译时,出现了这个错误:
BaseActivity cannot be provided without an @Provides-annotated method.
所以,我的问题是:如何构造函数注入抽象 class。我尝试了很多东西但没有成功,比如在 Hilt 模块中:
@Provides
@Singleton
fun provideBaseActivity(): BaseActivity{
return BaseActivity() // Of course, it can't work cause it's an abstract class
}
或者(就像我对 Dagger 所做的那样):
@Provides
@PerActivity
fun appCompatActivity(baseActivity: BaseActivity) = baseActivity as AppCompatActivity
此外,我只是 Hilt 的初学者,所以,也许我错过了什么。我会继续搜索:)
感谢您的宝贵时间和回答:)
编辑:
我自己搜索了几天,这似乎有效,但似乎不太好...
@Singleton
@Provides
fun provideBaseActivity(baseActivity: BaseActivity): AppCompatActivity {
return baseActivity
}
但前提是我像这样放置我的 baseActivity :
open class BaseActivity Inject constructor() : AppCompatActivity()
但是,在那之后,如果我尝试像这样在我的 TestComponentImpl 中使用注入的 baseActivity(就像我在 Hilt 之前使用 Dagger 所做的那样):
override fun displayError() {
Snackbar.make(
baseActivity.findViewById(android.R.id.content),
"My error text",
Snackbar.LENGTH_LONG
).apply {
show()
}
我遇到另一个错误:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
所以我不认为我的 baseActivity 注入做得很好。我会继续调查 ;)
有点hacky(type-casting)但应该可以用(未经测试,记下我的头顶所以随时让我知道如果某些东西没有按预期工作):
创建这样的 Module
:
@Module
@InstallIn(ActivityComponent::class)
object BaseActivityModule {
@Provides
fun provideBaseActivity(activity: Activity): BaseActivity {
check(activity is BaseActivity) { "Every Activity is expected to extend BaseActivity" }
return activity as BaseActivity
}
}
最后一个演员as BaseActivity
可能是不必要的。 Kotlin 编译器应该处理这个问题。
@Boysteuf @Bartek Lipinski
遇到以下错误:
error: [Dagger/MissingBinding] android.app.Activity cannot be provided without an @Inject constructor or an @Provides-annotated method.
public abstract static class SingletonC implements EzeApp_GeneratedInjector,
^
android.app.Activity is injected at
com.ezetap.consumerpaymentsdk.di.module.BaseActivityModule.provideBaseActivity(activity)
com.ezetap.consumerpaymentsdk.base.BaseSDKActivity is injected at
com.ezetap.consumerpaymentsdk.di.module.AppModule.provideServicePresenterPresenter(baseSDKActivity, …)
com.ezetap.consumerpaymentsdk.presenters.ServicePresenter is injected at
com.ezetap.consumerpaymentsdk.activity.ServiceSDKActivity.presenter
com.ezetap.consumerpaymentsdk.activity.ServiceSDKActivity is injected at
com.ezetap.consumerpaymentsdk.activity.ServiceSDKActivity_GeneratedInjector.injectServiceSDKActivity(com.ezetap.consumerpaymentsdk.activity.ServiceSDKActivity) [com.ezetap.consumerpaymentsdk.base.EzeApp_HiltComponents.SingletonC → com.ezetap.consumerpaymentsdk.base.EzeApp_HiltComponents.ActivityRetainedC → com.ezetap.consumerpaymentsdk.base.EzeApp_HiltComponents.ActivityC]
The following other entry points also depend on it:
com.ezetap.consumerpaymentsdk.activity.SimActivity_GeneratedInjector.injectSimActivity(com.ezetap.consumerpaymentsdk.activity.SimActivity) [com.ezetap.consumerpaymentsdk.base.EzeApp_HiltComponents.SingletonC → com.ezetap.consumerpaymentsdk.base.EzeApp_HiltComponents.ActivityRetainedC → com.ezetap.consumerpaymentsdk.base.EzeApp_HiltComponents.ActivityC]
AppModule
@Module(includes = [NetworkModule::class , BaseActivityModule::class ])
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun provideBasePresenter(baseSDKActivity: BaseSDKActivity ,ezeApi: EzeApi, @ApplicationContext context: Context ) : BaseSDKPresenter {
return BaseSDKPresenter(baseSDKActivity, ezeApi , context )
}
@Provides
@Singleton
fun provideSimPresenter(baseSDKActivity: BaseSDKActivity, ezeApi: EzeApi , @ApplicationContext context: Context ) : SimPresenter {
return SimPresenter(baseSDKActivity , ezeApi , context)
}
@Provides
@Singleton
fun provideServicePresenterPresenter(baseSDKActivity: BaseSDKActivity,ezeApi: EzeApi , @ApplicationContext context: Context ) : ServicePresenter {
return ServicePresenter(baseSDKActivity , ezeApi , context)
}
}
BaseActivityModule
@Module
@InstallIn(ActivityComponent::class)
object BaseActivityModule {
@Provides
fun provideBaseActivity(activity :Activity): BaseSDKActivity {
check(activity is BaseSDKActivity) { "Every Activity is expected to extend BaseActivity" }
return activity as BaseSDKActivity
}
}
BaseSDKActivity
open class BaseSDKActivity @Inject constructor() : AppCompatActivity() {
}
BaseSDKPresenter
@ActivityScoped
open class BaseSDKPresenter @Inject constructor(private val baseSDKActivity: BaseSDKActivity , private val ezeApi: EzeApi ,
private val context: Context )