Android: как сделать многомодульную инъекцию компонентов dagger?

#android #dependency-injection #dagger-2

#Android #инъекция зависимостей #dagger-2

Вопрос:

У меня есть gradle multi-module dagger приложение для Android.

Внутри каждого модуля я делаю инъекцию через его собственный компонент, подобный этому:

MainApp.appComponent.inject(this) для модуля :app и BaseApp.appComponent.inject(this) для модуля :app:base .

Теперь пытаюсь сделать SharedPreferences оболочку доступной внутри app:base модуля. До этого момента все работало нормально, но после этого я столкнулся с этой ошибкой

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.alazar.tracker/com.alazar.tracker.MainActivity}: kotlin.UninitializedPropertyAccessException: lateinit property appComponent has not been initialized

Application.name свойство, указанное в Manifest.xml :app:base модуля.

Что я делаю не так и как это исправить? Спасибо за любое предложение.

MainActivity:

 class MainActivity : BaseActivity(), View.OnClickListener {

    @Inject
    lateinit var userManager: UserManagerInterface

    @Inject
    lateinit var preferences: PreferenceProvider

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        MainApp.appComponent.inject(this)

        binding = ActivityMainBinding.inflate(layoutInflater)

        binding.btnSignOut.setOnClickListener(this)
        binding.btnStart.setOnClickListener(this)
        binding.btnStop.setOnClickListener(this)

        if (!userManager.isAuthenticated()) {
            openPostActivity.launch(Intent(this, AuthActivity::class.java))
        } else {
            setContentView(binding.root)
            changeStatus(preferences.getServiceStatus())
        }
    }

}
 

MainApp:

     @MainScope
@Component(
    dependencies = [
    ],
    modules = [
        MainModule::class,
    ]
)

interface MainAppComponent {
    fun inject(activity: MainActivity)
    fun inject(activity: MapActivity)
}

@Module(
    includes = [
        AuthUserModule::class,
        BaseModule::class,
    ]
)
class MainModule


class MainApp : Application() {

    override fun onCreate() {
        super.onCreate()

        appComponent = DaggerMainAppComponent
            .builder()
            .build()
    }

    companion object {
        lateinit var appComponent: MainAppComponent
    }
}
 

BaseApp:

     @Singleton
@Component(
    modules = [
        BaseModule::class,
    ]
)

interface BaseComponent {
    fun inject(baseApp: BaseApp)
    fun inject(wrapper: SharedPrefWrapper)
}

@Module
class BaseModule constructor(private val application: Application) {
    @Provides
    fun provideContext() : Context = application.applicationContext

    @Provides
    fun provideSharedPreferences() : PreferenceProvider = SharedPrefWrapper(application.applicationContext)
}

class BaseApp : Application() {

    override fun onCreate() {
        super.onCreate()

        appComponent = DaggerBaseComponent
            .builder()
            .baseModule(BaseModule(this))
            .build()
    }

    companion object {
        lateinit var appComponent: BaseComponent
    }
}
 

Оболочка SharedPreferences

     class SharedPrefWrapper @Inject constructor(private val context: Context) : PreferenceProvider {

    init {
        BaseApp.appComponent.inject(this)
        Log.d("************ CONTEXT", context.toString())
    }

    private var preferences: SharedPreferences = context.getSharedPreferences(
        context.getString(R.string.shared_preference_name),
        AppCompatActivity.MODE_PRIVATE
    )

    override fun saveServiceStatus(status: Boolean) {
        val editor = preferences.edit()
        editor.putBoolean(context.getString(R.string.preference_service_param), status)
        editor.apply()
    }

    override fun getServiceStatus(): Boolean {
        return preferences.getBoolean(context.getString(R.string.preference_service_param), false)
    }
}