Почему не инжектится переменная Dagger2

246
15 декабря 2017, 03:04

Вот сделал имплементацию дагера и вроде как все работет, вот только context переменная не хочет инжектиться

Вот так я хочу ее получить в своем baseactivity

abstract class SunshineBaseActivity: AppCompatActivity(), IScreenNavigator
{
@Inject lateinit var mContext: Context
....//
}

Теперь вот мой application

class SunshineApp: Application()
{
companion object
{
    fun getInstance(context: Context): SunshineApp
    {
        return context.applicationContext as SunshineApp
    }
}
val appComponent: AppComponent by lazy {
DaggerAppComponent.builder().appModule(AppModule(this)).
networkModule(NetworkModule()).build()
}
override fun onCreate()
{
    super.onCreate()
    appComponent.inject(this)
}
}

Сам Context я получаю в AppModule

@Module
class AppModule(val app: SunshineApp)
{
@Provides
@Singleton
fun provideApp() = app
@Provides
@Singleton
fun provideContext(): Context
{
    return app
}
@Provides
@Singleton
fun getLayoutInflater(app: SunshineApp): LayoutInflater
{
    return LayoutInflater.from(app)
}
}

Что сделал не так?

ПРАВКА

Как мне казалось, что вот этот метод

override fun onCreate()
{
super.onCreate()
appComponent.inject(this)
}

который указан в этом классе

class SunshineApp: Application()

как раз и делает инжект для всего дагера, и мне не нужно будет вызывать инжект в каждом активити. Но нет, получается так, что нужно

Немного поменял структуру, теперь выглядит так

abstract class SunshineBaseActivity: AppCompatActivity(), IScreenNavigator
{
@Inject lateinit var mContext: Context
private val mComponent: AppComponent by lazy {
    SunshineApp.getInstance(this).appComponent
}
override fun onCreate(savedInstanceState: Bundle?)
{
    super.onCreate(savedInstanceState)
    mComponent.inject(this)
..///
}
..///
}

И Application выглядит так

class SunshineApp: Application()
{
companion object
{
    fun getInstance(context: Context): SunshineApp
    {
        return context.applicationContext as SunshineApp
    }
}
val appComponent: AppComponent by lazy {
    DaggerAppComponent.builder().appModule(AppModule(this)).networkModule(NetworkModule()).build()
}
}

И вроде все работает, но только странно получается, что если мне нужно инжектнуть контекст в другом активити которое наследуется от SunshineBaseActivity например PreviewActivity : SunshineBaseActivity то я не могу в inject() как параметр передать this

Кстати вот мой компонент

@PerApplication
@Component(modules = [(AppModule::class), (NetworkModule::class), 
(DrawerModule::class)])
interface AppComponent
{
fun inject(app: SunshineBaseActivity)
fun plus(matchesModule: PreviewModule): PreviewComponent
}

Так вот не могу я передать this потому , что он хочет получить SunshineBaseActivity и странно получается то, что он как будто не видит, что PreviewActivity является наследником.

Все работает только если в компонент добавить еще одну строчку, вот так

@PerApplication
@Component(modules = [(AppModule::class), (NetworkModule::class), 
(DrawerModule::class)])
interface AppComponent
{
fun inject(app: SunshineBaseActivity)
fun inject(app: PreviewActivity)
fun plus(matchesModule: PreviewModule): PreviewComponent
}

Но как то странно выходит... Теперь для каждого нового активити в котором мне нужно использовать AppModule прийдется добавлять строчку с инжектом в компонент? Или я что то не так понимаю?

Answer 1

AppComponent#inject(this) надо явно вызывать в каждой конкретной реализации к-л класса. Т.е., если у вас есть базовый абстрактный класс, то в нём inject() вызывать не надо, а вот во всех его наследниках надо. В т.ч. наследниках не абстрактных классов.

Т.е. правило - inject() надо вызывать для всех неабстрактных классов для которых инъекции осуществляются не через конструктор. Только так Dagger сможет сгенерировать код для инъекций.

Если бы использовалась инъекция через конструктор, то вызывать AppComponent#inject(this) нигде не было бы надо, но для каждого неабстрактного класса надо было бы написать @Provides метод.

Т.к. активити/фрагменты/сервисы создаются системой и их конструкторы использовать нельзя, то надо вызывать AppComponent#inject(this) в каждом конкретном классе.

READ ALSO
Заменить итератор циклом

Заменить итератор циклом

Подскажите пожалуйста, как переписать фрагмент кода, используя вместо итератора цикл:

196
Java Swing: длина \t в JTextPane

Java Swing: длина \t в JTextPane

Делаю редактор кода The C language на платформе Java SwingКак изменить длину символа табуляции в JTextPane с 8 до 4 или 2

213
Утечка памяти ли это? Как исправить?

Утечка памяти ли это? Как исправить?

Пишу Android приложение с использованием таких библиотек:

175