Внедрить Activity в другой зависимый класс - PullRequest
0 голосов
/ 14 июля 2020

Я уже некоторое время пытаюсь правильно настроить код dagger2 в моем проекте, но, похоже, не могу понять, как это сделать правильно. Мое приложение выглядит примерно так:

class MyApplication : DaggerApplication() {
...
}
class MainActivity : DaggerAppCompatActivity() {
...
}
abstract class BaseFragment() : DaggerFragment() {
    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory
...
    fun <T : ViewModel> getViewModel(c: Class<T>): T = getViewModel(c, requireActivity())
    fun <T : ViewModel> getViewModel(c: Class<T>, owner: ViewModelStoreOwner): T{
        return ViewModelProvider(owner, viewModelFactory)[c]
    }
}
class AConcreteFragment : BaseFragment() {

    private lateinit var viewModel: AViewModel

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = getViewModel(AViewModel::class.java)
}
class AViewModel @Inject constructor(private val someApiManager: SomeApiManager ) : ViewModel() {
...
}
class SomeApiManager @Inject constructor(private val activity: MainActivity) {
...
    fun authenticate(){
        3rdPartyLibrary.openLoginActivity(activity,...)
    }
}

До того, как я представил SomeApiManager, который зависит от MainActivity, все работало нормально. Затем я установил dagger2 примерно так:

@Singleton
@Component(
    modules = [
        AndroidSupportInjectionModule::class,
        ApplicationModule::class,
        FragmentBuilder::class,
        ViewModelModule::class,
        ...
    ]
)
interface ApplicationComponent: AndroidInjector<MyApplication> {
...
}
@Module
public abstract class FragmentBuilder {
    @ContributesAndroidInjector()
    abstract fun bindAConcreteFragment(): AConcreteFragment?
    ...
}
@Singleton
class ViewModelFactory @Inject constructor(private val viewModels: MutableMap<Class<out ViewModel>, Provider<ViewModel>>) : ViewModelProvider.Factory {
...
}
@Module
abstract class ViewModelModule {

    @Binds
    internal abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory

    @Binds
    @IntoMap
    @ViewModelKey(AViewModel::class)
    internal abstract fun aViewModel(viewModel: AViewModel): ViewModel
...
}

Но как изменить мой код dagger2, чтобы он мог предоставлять MainActivity на SomeApiManager?

1 Ответ

0 голосов
/ 14 июля 2020

Как упоминал @DavidMedenjak, я неправильно определил масштаб. Мой модифицированный код dagger2 теперь выглядит следующим образом:

@Singleton
@Component(
    modules = [
        AndroidSupportInjectionModule::class,
        ApplicationModule::class,
        ActivityBuilder::class,
        ...
    ]
)
interface ApplicationComponent: AndroidInjector<MyApplication> {
...
}

@Module()
public abstract class ActivityBuilder {

    @ActivityScope
    @ContributesAndroidInjector(modules = [
        FragmentBuilder::class,
        ViewModelModule::class
    ])
    abstract fun bindMainActivity(): MainActivity?

}

@Module
public abstract class FragmentBuilder {
    @FragmentScope
    @ContributesAndroidInjector()
    abstract fun bindAConcreteFragment(): AConcreteFragment?
    ...
}

@ActivityScope
class ViewModelFactory @Inject constructor(private val viewModels: MutableMap<Class<out ViewModel>, Provider<ViewModel>>) : ViewModelProvider.Factory {
...
}

@Module
abstract class ViewModelModule {

    @Binds
    internal abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory

    @Binds
    @IntoMap
    @ViewModelKey(AViewModel::class)
    internal abstract fun aViewModel(viewModel: AViewModel): ViewModel
...
}

Не уверен, что он полностью верен, но все еще не совсем понимаю все, что происходит. Но это работает.

...