프로젝트에 Dagger 2를 추가하려고합니다. 조각에 ViewModels (AndroidX Architecture 구성 요소)를 주입 할 수있었습니다.
동일한 조각의 두 인스턴스 (각 탭마다 약간의 변경 만) 가있는 ViewPager가 있으며 각 탭 LiveData
에서 (API에서) 데이터 변경에 대해 업데이트 되는 것을 관찰하고 있습니다.
문제는 API 응답이 와서 업데이트 할 LiveData
때 현재 보이는 조각의 동일한 데이터가 모든 탭의 관찰자에게 전송된다는 것입니다. (이것은 아마도의 범위 때문이라고 생각합니다 ViewModel
).
이것이 내 데이터를 관찰하는 방법입니다.
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
activityViewModel.expenseList.observe(this, Observer {
swipeToRefreshLayout.isRefreshing = false
viewAdapter.setData(it)
})
....
}
ViewModel
s 를 제공하기 위해이 클래스를 사용하고 있습니다 .
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
지점 에서 접근 방식을 사용하지 않습니까? 왜 범위가 필요합니까?