簡體   English   中英

使用 HILT 注入抽象 class(基本活動)

[英]Inject abstract class (base activity) with HILT

我剛剛開始嘗試在我非常簡單的項目中使用 Hilt。 現在一切都在 Dagger2 上,但我想遷移到 Hilt。

我有一個活動:

@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 { ... 
    }
}

但是,當我嘗試編譯時,出現此錯誤:

如果沒有 @Provides-annotated 方法,就無法提供 BaseActivity。

所以,我的問題是:如何構造函數注入一個抽象的 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(類型轉換)但應該可以工作(未經測試,寫下我的頭頂,所以如果有什么不按預期工作,請隨時告訴我):

創建這樣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]

應用模塊

@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)
    }

}

基本活動模塊

@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 )

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM