J'essaie d'ajouter Dagger 2 à mon projet. J'ai pu injecter ViewModels (composant AndroidX Architecture) pour mes fragments.
J'ai un ViewPager qui a 2 instances du même fragment (seulement un changement mineur pour chaque onglet) et dans chaque onglet, j'observe un LiveDatapour être mis à jour sur le changement de données (à partir de l'API).
Le problème est que lorsque la réponse api arrive et met à jour le LiveData, les mêmes données dans le fragment actuellement visible sont envoyées aux observateurs dans tous les onglets. (Je pense que c'est probablement à cause de la portée de la ViewModel).
Voici comment j'observe mes données:
override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        activityViewModel.expenseList.observe(this, Observer {
            swipeToRefreshLayout.isRefreshing = false
            viewAdapter.setData(it)
        })
    ....
}
J'utilise cette classe pour fournir ViewModels:
class ViewModelProviderFactory @Inject constructor(creators: MutableMap<Class<out ViewModel?>?, Provider<ViewModel?>?>?) :
    ViewModelProvider.Factory {
    private val creators: MutableMap<Class<out ViewModel?>?, Provider<ViewModel?>?>? = creators
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        var creator: Provider<out ViewModel?>? = creators!![modelClass]
        if (creator == null) { // if the viewmodel has not been created
// loop through the allowable keys (aka allowed classes with the @ViewModelKey)
            for (entry in creators.entries) { // if it's allowed, set the Provider<ViewModel>
                if (modelClass.isAssignableFrom(entry.key!!)) {
                    creator = entry.value
                    break
                }
            }
        }
        // if this is not one of the allowed keys, throw exception
        requireNotNull(creator) { "unknown model class $modelClass" }
        // return the Provider
        return try {
            creator.get() as T
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
    }
    companion object {
        private val TAG: String? = "ViewModelProviderFactor"
    }
}
Je lie mon ViewModelcomme ceci:
@Module
abstract class ActivityViewModelModule {
    @MainScope
    @Binds
    @IntoMap
    @ViewModelKey(ActivityViewModel::class)
    abstract fun bindActivityViewModel(viewModel: ActivityViewModel): ViewModel
}
J'utilise @ContributesAndroidInjectorpour mon fragment comme ceci:
@Module
abstract class MainFragmentBuildersModule {
    @ContributesAndroidInjector
    abstract fun contributeActivityFragment(): ActivityFragment
}
Et j'ajoute ces modules à mon MainActivitysous - composant comme ceci:
@Module
abstract class ActivityBuilderModule {
...
    @ContributesAndroidInjector(
        modules = [MainViewModelModule::class, ActivityViewModelModule::class,
            AuthModule::class, MainFragmentBuildersModule::class]
    )
    abstract fun contributeMainActivity(): MainActivity
}
Voici mon AppComponent:
@Singleton
@Component(
    modules =
    [AndroidSupportInjectionModule::class,
        ActivityBuilderModule::class,
        ViewModelFactoryModule::class,
        AppModule::class]
)
interface AppComponent : AndroidInjector<SpenmoApplication> {
    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(application: Application): Builder
        fun build(): AppComponent
    }
}
J'étends DaggerFragmentet j'injecte ViewModelProviderFactorycomme ceci:
@Inject
lateinit var viewModelFactory: ViewModelProviderFactory
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
....
activityViewModel =
            ViewModelProviders.of(this, viewModelFactory).get(key, ActivityViewModel::class.java)
        activityViewModel.restartFetch(hasReceipt)
}
le keysera différent pour les deux fragments.
Comment puis-je m'assurer que seul l'observateur du fragment actuel est mis à jour.
EDIT 1 ->
J'ai ajouté un exemple de projet avec l'erreur. Il semble que le problème se produit uniquement lorsqu'une étendue personnalisée est ajoutée. Veuillez consulter l'exemple de projet ici: Lien Github
masterbranche a l'application avec le problème. Si vous actualisez un onglet (faites glisser pour actualiser), la valeur mise à jour se reflète dans les deux onglets. Cela ne se produit que lorsque j'y ajoute une étendue personnalisée ( @MainScope).
working_fine branche a la même application sans portée personnalisée et fonctionne bien.
Veuillez me faire savoir si la question n'est pas claire.
working_finebranche? Pourquoi avez-vous besoin de la portée?