我有一个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)
}