Различные экземпляры ViewModel из одного и того же компонента - PullRequest
0 голосов
/ 31 мая 2018

У меня есть действие с ViewPager, которое отображает те же данные либо в виде карты (страница 0), либо в списке (страница 1).Происходит некоторая фильтрация, поэтому я подумал, что эта фильтрация может быть применена в упражнении (которое содержит представления) и передана в ViewModel, который через LiveData обновит оба Fragments (просмотр карты и список)

Теория звучит хорошо, но когда я ее реализую, мой компонент всегда вводит новые экземпляры для действия и обоих фрагментов.Я нашел, напечатав следующие строки:

05-31 13:36:16.832 16091-16091/W/DashboardActivity: Hello com.myapp.sample.ui.dashboard.DashboardViewModel@b8bb537 from com.myapp.sample.ui.dashboard.DashboardActivity@899a9f6
05-31 13:36:17.133 16091-16091/W/MyPicksMapFragment: Hello com.myapp.sample.ui.dashboard.DashboardViewModel@59e2119 from MapFragment{72070f4 #1 id=0x7f090137 android:switcher:2131296567:0}
05-31 13:36:18.139 16091-16091/W/MyPicksListFragment: Hello com.myapp.sample.ui.dashboard.DashboardViewModel@58a33fb from ListFragment{2be0446 #2 id=0x7f090137 android:switcher:2131296567:1}

Эта строка подтверждает то же самое Component:

05-31 13:47:49.509 18411-18411/com.myapp.sample.dev.debug E/DashboardActivity: Saying hello from component com.myapp.sample.di.application.DaggerApplicationComponent$ControllerComponentImpl@4ccc864 within com.myapp.sample.ui.dashboard.DashboardActivity@57a81f7
05-31 13:47:50.350 18411-18411/com.myapp.sample.dev.debug E/MyPicksMapFragment: Saying hello from component com.myapp.sample.di.application.DaggerApplicationComponent$ControllerComponentImpl@4ccc864 within MyPicksMapFragment{3443332 #1 id=0x7f090137 android:switcher:2131296567:0}
05-31 13:47:51.194 18411-18411/com.myapp.sample.dev.debug E/MyPicksListFragment: Saying hello from component com.myapp.sample.di.application.DaggerApplicationComponent$ControllerComponentImpl@4ccc864 within MyPicksListFragment{e520996 #2 id=0x7f090137 android:switcher:2131296567:1}

Это моя деятельность:

class DashboardActivity : BaseActivity<DashboardViewModel>() {


         override fun inject() {
             Timber.e("Saying hello from component $component within $this")
             component.inject(this)
         }
   }

Базовая активность:

abstract class BaseActivity<E : ViewModel> : AppCompatActivity() {

 val component by lazy { (application as SoulpicksApp)
                     .applicationComponent
                     .plus(
                             ControllerModule(this)
                     )
             }


    @Inject
    protected lateinit var viewModel: E

    }

    @CallSuper
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)

       inject()
  }

Один из фрагментов:

  class MyPicksListFragment : BaseFragment<DashboardViewModel>() {
    override fun inject() {
            var component = (activity as DashboardActivity).component
            Timber.e("Saying hello from component $component within $this")
            component.inject(this)
        }

  }

Базовый фрагмент:

  abstract class BaseFragment<E : ViewModel> : Fragment() {

    @Inject
    protected lateinit var viewModel: E

    @CallSuper
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        inject()
    }



  }

Компонент приложения:

@Module(includes = [ViewModelModule::class])
class ApplicationModule(val application: Application) {
(...)
}

ViewModelFactory:

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


    override fun <T : ViewModel?> create(modelClass: Class<T>): T = viewModels[modelClass]?.get() as T
}

@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
@MapKey
internal annotation class ViewModelKey(val value: KClass<out ViewModel>)

ViewModelModule:

@Module
abstract class ViewModelModule {

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

    @Binds
    @IntoMap
    @ViewModelKey(DashboardViewModel::class)
    internal abstract fun dashboardViewModel(viewModel: DashboardViewModel): ViewModel

}

Компонент контроллера:

@Module(includes = [ViewContainerModule::class])
class ControllerModule(val activity: FragmentActivity) {

    @Provides
    @ControllerScope
    fun context(): Context = activity

    @Provides
    @ControllerScope
    fun activity() = activity

    @Provides
    @ControllerScope
    fun layoutInflater() = activity.layoutInflater

    @Provides
    @ControllerScope
    fun fragmentManager(): android.support.v4.app.FragmentManager = activity.supportFragmentManager

    @Provides
    @ControllerScope
    fun smsAuthManager(context: Context) = SmsAuthManager(context)


    @Provides
    @ControllerScope
    fun provideConnectivityManager(context: Context): ConnectivityManager =
            context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

    @Provides
    @ControllerScope
    fun provideNetworkInteractor(networkInteractor: NetworkInteractorImpl): NetworkInteractor = networkInteractor

    @Provides
    @ControllerScope
    fun provideLocationManager(context: Context): RxLocationManager = RxLocationManagerImpl(context)

    @Provides
    @ControllerScope
    fun provideNavigationController(activity: FragmentActivity) = NavigationController(activity)


}
...