来自同一Component的不同ViewModel实例

时间:2018-05-31 11:48:35

标签: android dagger-2 android-architecture-components

我有一个ViewPager的活动,它在地图视图(第0页)或列表(第1页)中显示相同的数据。有一些过滤发生,所以我认为这个过滤可以应用于活动(包含视图)并提供给ViewModel,通过LiveData将更新Fragments(mapview)并列出)

理论听起来不错但是当我实现它时,我的组件总是为活动和两个片段注入新的实例。我通过打印以下几行找到了:

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)


}

0 个答案:

没有答案