Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to inject shared one instance of ViewModule to different fragments? #23

Closed
DigitalKoi opened this issue Jul 23, 2020 · 4 comments
Closed
Labels
question Further information is requested

Comments

@DigitalKoi
Copy link

is it possible to inject the same veivmodel into different fragments? I mean BaseFragment<FragmentSomeBinding, SharedViewModel>

@vmadalin
Copy link
Owner

Hi @DigitalKoi, First of all, thanks for your question. The quick answer is yes it's possible, but let explain how to do it.

Each ViewModel is provided by the specific feature dagger module that is allocated under di folder, you can find a sample of this here. That means that on the new Fragment where you want to reuse the ViewModel you should extend from the BaseFragment as you said and on the method onInitDependencyInjection() you should to inject the Dagger graph specifying the module which provides you the ViewModule.

You cand have just one Dagger module for both Fragments or create a new one for each that I consider like a better approach to avoid to have unnecessary providers. Another way is to create a base class that provides the viewModel.

@vmadalin vmadalin added the question Further information is requested label Jul 24, 2020
@DigitalKoi
Copy link
Author

DigitalKoi commented Jul 25, 2020

when I try to do something like this

    @FeatureScope
    fun provideFragment(
        viewModel: viewModel
    ) = fragment.viewModel {
        viewModel
    }

    @Provides
    @FeatureScope
    fun provideViewModel(
        repository: Repository
    ) = ViewModel(
        repository = repository
    )

I receive message Found a dependency cycle. How I understand problem is in @Inject annotation in BaseFragment

@vmadalin
Copy link
Owner

Please correct me if I'm wrong @DigitalKoi. I'm confused about the provideFragment that takes as a param viewModel to return again the viewModel. In addition, it should include @Provides annotation. Let me to share with you the way that I have in mind.

Basically the BaseFragment forces you to have at least one ViewModel that one is injected by the SpecificFragment on onInitDependencyInjection if you want to have an additional ViewModel you should declare this one on the SpecificFragment class by the:

 @Inject
  lateinit var secondViewModel: SecondViewModelClass

For my point of view you should have the following code, and to make it easier I will use code naming classes. Imagine that I want to use the CharacterDetailViewModel sharing it between CharacterDetailFragment and CharacterListFragment. Right now we already provide an instance of the CharacterDetailViewModel on the specific module and if we want to reuse the CharacterDetailViewModel we should to provide it again.

For this reason, we should include it to CharactersListModule by adding the following, exactly the same provider like on CharacterDetailModule:

@FeatureScope
    @Provides
    fun providesCharacterDetailViewModel(
        marvelRepository: MarvelRepository,
        characterFavoriteRepository: CharacterFavoriteRepository,
        characterDetailMapper: CharacterDetailMapper
    ) = fragment.viewModel {
        CharacterDetailViewModel(
            marvelRepository = marvelRepository,
            characterFavoriteRepository = characterFavoriteRepository,
            characterDetailMapper = characterDetailMapper
        )
    }

And after that depends on our propose we have the following scenarios:

  • I only want one ViewModel defined for CharactersListFragment in that case you just replace the class definition to:
class CharactersListFragment :
    BaseFragment<FragmentCharactersListBinding, CharacterDetailViewModel>(// now this use the CharacterDetailViewModel 
        layoutId = R.layout.fragment_characters_list
    )
  • In case we want to keep the both ViewModels in this case the CharactersListViewModel and CharacterDetailViewModel. One of them will be the default one that you need to specify to BaseFragment and to another one you should declare it as I mentioned before with Inject annotation.
    And on the onInitDependencyInjection() you just need to keep the current implementation of this.

Please let me know if this helps you

@DigitalKoi
Copy link
Author

@vmadalin Thanks a lot!)

@vmadalin vmadalin closed this as completed Aug 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants