【发布时间】:2020-01-30 12:36:14
【问题描述】:
我正在尝试将 Dagger 2 添加到我的项目中。我能够为我的片段注入 ViewModels(AndroidX 架构组件)。
我有一个 ViewPager,它有 2 个相同片段的实例(每个选项卡只有很小的更改),在每个选项卡中,我都在观察 LiveData 以获取有关数据更改的更新(来自 API)。
问题是,当 api 响应到来并更新 LiveData 时,当前可见片段中的相同数据正在发送给所有选项卡中的观察者。(我认为这可能是因为ViewModel 的范围。
这就是我观察数据的方式:
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
activityViewModel.expenseList.observe(this, Observer {
swipeToRefreshLayout.isRefreshing = false
viewAdapter.setData(it)
})
....
}
我正在使用这个类来提供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"
}
}
我正在像这样绑定我的ViewModel:
@Module
abstract class ActivityViewModelModule {
@MainScope
@Binds
@IntoMap
@ViewModelKey(ActivityViewModel::class)
abstract fun bindActivityViewModel(viewModel: ActivityViewModel): ViewModel
}
我正在为我的片段使用@ContributesAndroidInjector,如下所示:
@Module
abstract class MainFragmentBuildersModule {
@ContributesAndroidInjector
abstract fun contributeActivityFragment(): ActivityFragment
}
我将这些模块添加到我的MainActivity 子组件中,如下所示:
@Module
abstract class ActivityBuilderModule {
...
@ContributesAndroidInjector(
modules = [MainViewModelModule::class, ActivityViewModelModule::class,
AuthModule::class, MainFragmentBuildersModule::class]
)
abstract fun contributeMainActivity(): MainActivity
}
这是我的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
}
}
我正在扩展DaggerFragment 并像这样注入ViewModelProviderFactory:
@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)
}
两个片段的key 将不同。
如何确保只有当前片段的观察者正在更新。
编辑 1 ->
我添加了一个错误的示例项目。似乎只有在添加自定义范围时才会出现问题。请在此处查看示例项目:Github link
master 分支的应用程序存在问题。如果您刷新任何选项卡(滑动以刷新),更新的值将反映在两个选项卡中。仅当我向其添加自定义范围时才会发生这种情况 (@MainScope)。
working_fine 分支具有相同的应用程序,没有自定义范围并且工作正常。
如果问题不清楚,请告诉我。
【问题讨论】:
-
我不明白你为什么不使用
working_fine分支的方法?为什么需要范围? -
@azizbekian 我目前正在使用工作正常的分支。但我想知道,为什么使用范围会破坏这个。
标签: android android-viewpager dagger-2 androidx android-mvvm