Hilt: introduce MavericksComponent and try on RoomList
This commit is contained in:
parent
ff53cf4db9
commit
f8d208fb4f
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.core.di
|
||||||
|
|
||||||
|
import com.airbnb.mvrx.MavericksState
|
||||||
|
import com.airbnb.mvrx.MavericksViewModel
|
||||||
|
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||||
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
|
import dagger.hilt.DefineComponent
|
||||||
|
import dagger.hilt.EntryPoint
|
||||||
|
import dagger.hilt.EntryPoints
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To connect Mavericks ViewModel creation with Hilt's dependency injection, add the following Factory and companion object to your MavericksViewModel.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* class MyViewModel @AssistedInject constructor(...): MavericksViewModel<MyState>(...) {
|
||||||
|
*
|
||||||
|
* @AssistedFactory
|
||||||
|
* interface Factory : AssistedViewModelFactory<MyViewModel, MyState> {
|
||||||
|
* ...
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* companion object : MavericksViewModelFactory<MyViewModel, MyState> by hiltMavericksViewModelFactory()
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline fun <reified VM : MavericksViewModel<S>, S : MavericksState> hiltMavericksViewModelFactory() = HiltMavericksViewModelFactory<VM, S>(VM::class.java)
|
||||||
|
|
||||||
|
class HiltMavericksViewModelFactory<VM : MavericksViewModel<S>, S : MavericksState>(
|
||||||
|
private val viewModelClass: Class<out MavericksViewModel<S>>
|
||||||
|
) : MavericksViewModelFactory<VM, S> {
|
||||||
|
|
||||||
|
override fun create(viewModelContext: ViewModelContext, state: S): VM {
|
||||||
|
// We want to create the ViewModelComponent. In order to do that, we need to get its parent: ActivityComponent.
|
||||||
|
val componentBuilder = EntryPoints.get(viewModelContext.app(), CreateMavericksViewModelComponent::class.java).mavericksViewModelComponentBuilder()
|
||||||
|
val viewModelComponent = componentBuilder.build()
|
||||||
|
val viewModelFactoryMap = EntryPoints.get(viewModelComponent, HiltMavericksEntryPoint::class.java).viewModelFactories
|
||||||
|
val viewModelFactory = viewModelFactoryMap[viewModelClass]
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val castedViewModelFactory = viewModelFactory as? MavericksAssistedViewModelFactory<VM, S>
|
||||||
|
return castedViewModelFactory?.create(state) as VM
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hilt's ViewModelComponent's parent is ActivityRetainedComponent but there is no easy way to access it. SingletonComponent should be sufficient
|
||||||
|
* because the ViewModel that gets created is the only object with a reference to the created component so the lifecycle of it will
|
||||||
|
* still be correct.
|
||||||
|
*/
|
||||||
|
@MavericksViewModelScoped
|
||||||
|
@DefineComponent(parent = SingletonComponent::class)
|
||||||
|
interface MavericksViewModelComponent
|
||||||
|
|
||||||
|
@DefineComponent.Builder
|
||||||
|
interface MavericksViewModelComponentBuilder {
|
||||||
|
fun build(): MavericksViewModelComponent
|
||||||
|
}
|
||||||
|
|
||||||
|
@EntryPoint
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
interface CreateMavericksViewModelComponent {
|
||||||
|
fun mavericksViewModelComponentBuilder(): MavericksViewModelComponentBuilder
|
||||||
|
}
|
||||||
|
|
||||||
|
@EntryPoint
|
||||||
|
@InstallIn(MavericksViewModelComponent::class)
|
||||||
|
interface HiltMavericksEntryPoint {
|
||||||
|
val viewModelFactories: Map<Class<out MavericksViewModel<*>>, MavericksAssistedViewModelFactory<*, *>>
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.core.di
|
||||||
|
|
||||||
|
import com.airbnb.mvrx.MavericksState
|
||||||
|
import com.airbnb.mvrx.MavericksViewModel
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This factory allows Mavericks to supply the initial or restored [MavericksState] to Hilt.
|
||||||
|
*
|
||||||
|
* Add this interface inside of your [MavericksViewModel] class then create the following Hilt module:
|
||||||
|
*
|
||||||
|
* @Module
|
||||||
|
* @InstallIn(MavericksViewModelComponent::class)
|
||||||
|
* interface ViewModelsModule {
|
||||||
|
* @Binds
|
||||||
|
* @IntoMap
|
||||||
|
* @ViewModelKey(MyViewModel::class)
|
||||||
|
* fun myViewModelFactory(factory: MyViewModel.Factory): AssistedViewModelFactory<*, *>
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* If you already have a ViewModelsModule then all you have to do is add the multibinding entry for your new [MavericksViewModel].
|
||||||
|
*/
|
||||||
|
interface MavericksAssistedViewModelFactory<VM : MavericksViewModel<S>, S : MavericksState> {
|
||||||
|
fun create(state: S): VM
|
||||||
|
}
|
@ -14,16 +14,20 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.app.features.home.room.list
|
package im.vector.app.core.di
|
||||||
|
|
||||||
import dagger.Binds
|
import dagger.Binds
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.hilt.migration.DisableInstallInCheck
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.multibindings.IntoMap
|
||||||
|
import im.vector.app.features.home.room.list.RoomListViewModel
|
||||||
|
|
||||||
@DisableInstallInCheck
|
@InstallIn(MavericksViewModelComponent::class)
|
||||||
@Module
|
@Module
|
||||||
abstract class RoomListModule {
|
interface MavericksViewModelModule {
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun providesRoomListViewModelFactory(factory: RoomListViewModelFactory): RoomListViewModel.Factory
|
@IntoMap
|
||||||
|
@MavericksViewModelKey(RoomListViewModel::class)
|
||||||
|
fun roomListViewModelFactory(factory: RoomListViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
|
||||||
}
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.core.di
|
||||||
|
|
||||||
|
import javax.inject.Scope
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope annotation for bindings that should exist for the life of an MavericksViewModel.
|
||||||
|
*/
|
||||||
|
@Scope
|
||||||
|
annotation class MavericksViewModelScoped
|
@ -73,7 +73,6 @@ import im.vector.app.features.home.room.detail.timeline.reactions.ViewReactionsB
|
|||||||
import im.vector.app.features.home.room.detail.upgrade.MigrateRoomBottomSheet
|
import im.vector.app.features.home.room.detail.upgrade.MigrateRoomBottomSheet
|
||||||
import im.vector.app.features.home.room.detail.widget.RoomWidgetsBottomSheet
|
import im.vector.app.features.home.room.detail.widget.RoomWidgetsBottomSheet
|
||||||
import im.vector.app.features.home.room.filtered.FilteredRoomsActivity
|
import im.vector.app.features.home.room.filtered.FilteredRoomsActivity
|
||||||
import im.vector.app.features.home.room.list.RoomListModule
|
|
||||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet
|
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet
|
||||||
import im.vector.app.features.html.EventHtmlRenderer
|
import im.vector.app.features.html.EventHtmlRenderer
|
||||||
import im.vector.app.features.html.VectorHtmlCompressor
|
import im.vector.app.features.html.VectorHtmlCompressor
|
||||||
@ -253,7 +252,6 @@ interface ScreenComponentDependencies {
|
|||||||
ViewModelModule::class,
|
ViewModelModule::class,
|
||||||
FragmentModule::class,
|
FragmentModule::class,
|
||||||
HomeModule::class,
|
HomeModule::class,
|
||||||
RoomListModule::class,
|
|
||||||
ScreenModule::class
|
ScreenModule::class
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package im.vector.app.core.di
|
package im.vector.app.core.di
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import com.airbnb.mvrx.MavericksViewModel
|
||||||
import dagger.MapKey
|
import dagger.MapKey
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
@ -24,3 +25,8 @@ import kotlin.reflect.KClass
|
|||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
@MapKey
|
@MapKey
|
||||||
annotation class ViewModelKey(val value: KClass<out ViewModel>)
|
annotation class ViewModelKey(val value: KClass<out ViewModel>)
|
||||||
|
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@Target(AnnotationTarget.FUNCTION)
|
||||||
|
@MapKey
|
||||||
|
annotation class MavericksViewModelKey(val value: KClass<out MavericksViewModel<*>>)
|
||||||
|
@ -64,7 +64,6 @@ data class RoomListParams(
|
|||||||
|
|
||||||
class RoomListFragment @Inject constructor(
|
class RoomListFragment @Inject constructor(
|
||||||
private val pagedControllerFactory: RoomSummaryPagedControllerFactory,
|
private val pagedControllerFactory: RoomSummaryPagedControllerFactory,
|
||||||
val roomListViewModelFactory: RoomListViewModel.Factory,
|
|
||||||
private val notificationDrawerManager: NotificationDrawerManager,
|
private val notificationDrawerManager: NotificationDrawerManager,
|
||||||
private val footerController: RoomListFooterController,
|
private val footerController: RoomListFooterController,
|
||||||
private val userPreferencesProvider: UserPreferencesProvider
|
private val userPreferencesProvider: UserPreferencesProvider
|
||||||
|
@ -24,8 +24,13 @@ import com.airbnb.mvrx.Loading
|
|||||||
import com.airbnb.mvrx.MavericksViewModelFactory
|
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||||
import com.airbnb.mvrx.Success
|
import com.airbnb.mvrx.Success
|
||||||
import com.airbnb.mvrx.ViewModelContext
|
import com.airbnb.mvrx.ViewModelContext
|
||||||
|
import dagger.assisted.Assisted
|
||||||
|
import dagger.assisted.AssistedFactory
|
||||||
|
import dagger.assisted.AssistedInject
|
||||||
import im.vector.app.AppStateHandler
|
import im.vector.app.AppStateHandler
|
||||||
import im.vector.app.RoomGroupingMethod
|
import im.vector.app.RoomGroupingMethod
|
||||||
|
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||||
|
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||||
import im.vector.app.core.extensions.exhaustive
|
import im.vector.app.core.extensions.exhaustive
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
@ -48,8 +53,8 @@ import org.matrix.android.sdk.flow.flow
|
|||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class RoomListViewModel @Inject constructor(
|
class RoomListViewModel @AssistedInject constructor(
|
||||||
initialState: RoomListViewState,
|
@Assisted initialState: RoomListViewState,
|
||||||
private val session: Session,
|
private val session: Session,
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
private val appStateHandler: AppStateHandler,
|
private val appStateHandler: AppStateHandler,
|
||||||
@ -57,8 +62,9 @@ class RoomListViewModel @Inject constructor(
|
|||||||
private val autoAcceptInvites: AutoAcceptInvites
|
private val autoAcceptInvites: AutoAcceptInvites
|
||||||
) : VectorViewModel<RoomListViewState, RoomListAction, RoomListViewEvents>(initialState) {
|
) : VectorViewModel<RoomListViewState, RoomListAction, RoomListViewEvents>(initialState) {
|
||||||
|
|
||||||
interface Factory {
|
@AssistedFactory
|
||||||
fun create(initialState: RoomListViewState): RoomListViewModel
|
interface Factory: MavericksAssistedViewModelFactory<RoomListViewModel, RoomListViewState> {
|
||||||
|
override fun create(state: RoomListViewState): RoomListViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
private var updatableQuery: UpdatableLivePageResult? = null
|
private var updatableQuery: UpdatableLivePageResult? = null
|
||||||
@ -115,14 +121,7 @@ class RoomListViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object : MavericksViewModelFactory<RoomListViewModel, RoomListViewState> {
|
companion object : MavericksViewModelFactory<RoomListViewModel, RoomListViewState> by hiltMavericksViewModelFactory()
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
override fun create(viewModelContext: ViewModelContext, state: RoomListViewState): RoomListViewModel {
|
|
||||||
val fragment: RoomListFragment = (viewModelContext as FragmentViewModelContext).fragment()
|
|
||||||
return fragment.roomListViewModelFactory.create(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val roomListSectionBuilder = if (appStateHandler.getCurrentRoomGroupingMethod() is RoomGroupingMethod.BySpace) {
|
private val roomListSectionBuilder = if (appStateHandler.getCurrentRoomGroupingMethod() is RoomGroupingMethod.BySpace) {
|
||||||
RoomListSectionBuilderSpace(
|
RoomListSectionBuilderSpace(
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 New Vector Ltd
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package im.vector.app.features.home.room.list
|
|
||||||
|
|
||||||
import im.vector.app.AppStateHandler
|
|
||||||
import im.vector.app.core.resources.StringProvider
|
|
||||||
import im.vector.app.features.invite.AutoAcceptInvites
|
|
||||||
import im.vector.app.features.settings.VectorPreferences
|
|
||||||
import org.matrix.android.sdk.api.session.Session
|
|
||||||
import javax.inject.Inject
|
|
||||||
import javax.inject.Provider
|
|
||||||
|
|
||||||
class RoomListViewModelFactory @Inject constructor(private val session: Provider<Session>,
|
|
||||||
private val appStateHandler: AppStateHandler,
|
|
||||||
private val stringProvider: StringProvider,
|
|
||||||
private val vectorPreferences: VectorPreferences,
|
|
||||||
private val autoAcceptInvites: AutoAcceptInvites) :
|
|
||||||
RoomListViewModel.Factory {
|
|
||||||
|
|
||||||
override fun create(initialState: RoomListViewState): RoomListViewModel {
|
|
||||||
return RoomListViewModel(
|
|
||||||
initialState = initialState,
|
|
||||||
session = session.get(),
|
|
||||||
stringProvider = stringProvider,
|
|
||||||
appStateHandler = appStateHandler,
|
|
||||||
vectorPreferences = vectorPreferences,
|
|
||||||
autoAcceptInvites = autoAcceptInvites
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user