Last active
September 11, 2021 06:25
-
-
Save Zhuinden/06b86cb35cba0cb5e880505042e18c3d to your computer and use it in GitHub Desktop.
Dagger + ViewModel + SavedStateHandle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Singleton | |
@Component(modules = [AssistedInjectionModule::class]) | |
interface ApplicationComponent { | |
fun mySavedStateViewModelFactory(): MySavedStateViewModel.Factory | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@AssistedModule | |
@Module(includes = {AssistedInject_AssistedInjectionModule.class}) | |
public class AssistedInjectionModule { | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import androidx.lifecycle.observe | |
class MySavedStateFragment : Fragment(R.layout.my_saved_state_fragment) { | |
private val viewModel by navGraphSavedStateViewModels(R.id.registration_graph) { handle -> | |
Injector.get().mySavedStateViewModelFactory().create(handle) | |
} | |
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | |
super.onViewCreated(view, savedInstanceState) | |
val binding = MySavedStateFragmentBinding.bind(view) | |
viewModel.blah.observe(viewLifecycleOwner) { blah -> | |
// ... | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MySavedStateViewModel @AssistedInject constructor( | |
private val authenticationManager: AuthenticationManager, | |
@Assisted private val savedStateHandle: SavedStateHandle | |
) : ViewModel() { | |
@AssistedInject.Factory | |
interface Factory { | |
fun create(savedStateHandle: SavedStateHandle): MySavedStateViewModel | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
inline fun <reified T : ViewModel> SavedStateRegistryOwner.createAbstractSavedStateViewModelFactory( | |
arguments: Bundle, | |
crossinline creator: (SavedStateHandle) -> T | |
): ViewModelProvider.Factory { | |
return object : AbstractSavedStateViewModelFactory(this, arguments) { | |
@Suppress("UNCHECKED_CAST") | |
override fun <T : ViewModel?> create( | |
key: String, modelClass: Class<T>, handle: SavedStateHandle | |
): T = creator(handle) as T | |
} | |
} | |
inline fun <reified T : ViewModel> Fragment.navGraphSavedStateViewModels( | |
@IdRes navGraphId: Int, | |
crossinline creator: (SavedStateHandle) -> T | |
): Lazy<T> { | |
// Wrapped in lazy to not search the NavController each time we want the backStackEntry | |
val backStackEntry by lazy { findNavController().getBackStackEntry(navGraphId) } | |
return createViewModelLazy(T::class, storeProducer = { | |
backStackEntry.viewModelStore | |
}, factoryProducer = { | |
backStackEntry.createAbstractSavedStateViewModelFactory( | |
arguments = backStackEntry.arguments ?: Bundle(), creator = creator | |
) | |
}) | |
} | |
inline fun <reified T : ViewModel> Fragment.fragmentSavedStateViewModels( | |
crossinline creator: (SavedStateHandle) -> T | |
): Lazy<T> { | |
return createViewModelLazy(T::class, storeProducer = { | |
viewModelStore | |
}, factoryProducer = { | |
createAbstractSavedStateViewModelFactory(arguments ?: Bundle(), creator) | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I created a fork and added documentation to ViewModelUtils.kt as well as helper functions to manually inject CoroutineScope and a DispatcherProvider for Kotlin Coroutines in production and testing.