为何在自定义ViewModelProvider.Factory中使用CreationExtras?
我一直习惯通过自定义工厂类的构造函数传入参数来实例化ViewModel,搞不懂为什么要用到CreationExtras——明明直接传参给工厂就能完成自定义逻辑,它到底能解决什么问题?
两种写法对比
谷歌官方推荐的CreationExtras写法
class MyViewModel( private val myRepository: MyRepository, private val savedStateHandle: SavedStateHandle ) : ViewModel() { // ViewModel业务逻辑 // ... // 在伴生对象中定义工厂 companion object { val Factory: ViewModelProvider.Factory = object : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun <T : ViewModel> create( modelClass: Class<T>, extras: CreationExtras ): T { // 从Extras中获取Application实例 val application = checkNotNull(extras[APPLICATION_KEY]) // 通过Extras创建SavedStateHandle val savedStateHandle = extras.createSavedStateHandle() return MyViewModel( (application as MyApplication).myRepository, savedStateHandle ) as T } } } }
我习惯的构造函数传参写法
class MyFactory(val repository: MyRepository) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T { return MyViewModel(repository, extras.createSavedStateHandle()) as T } }
CreationExtras的核心价值
1. 自动获取框架内置依赖
像SavedStateHandle、Application这类由Jetpack框架管理的核心对象,不需要你手动传递给工厂——框架会自动把它们注入到CreationExtras中。比如示例里的savedStateHandle,如果用构造函数传参的方式,你得自己处理SavedState的创建逻辑,容易出错;而通过extras.createSavedStateHandle(),框架会帮你完成和组件生命周期的绑定。
2. 降低工厂与依赖来源的耦合
如果依赖需要从Application或者其他深层组件获取(比如示例中的MyRepository),用构造函数传参的话,你得先在外部拿到Application、获取Repository,再传给工厂。而用CreationExtras,工厂可以直接从Extras里取Application,再获取Repository,不用外部提前传递这些依赖,减少了代码的耦合度。
3. 无缝兼容Jetpack组件集成
在Compose、Navigation或者Hilt这类Jetpack组件中,框架会自动处理CreationExtras的填充。如果你的工厂依赖构造函数传参,可能需要手动适配这些组件的ViewModel创建逻辑;而基于CreationExtras的工厂可以直接和这些组件无缝配合,不用额外适配。
4. 统一依赖获取入口
你还可以自定义CreationExtras.Key,把自己的自定义依赖存入Extras中,这样工厂可以从同一个入口获取所有需要的依赖,不管是框架提供的还是自定义的,逻辑更统一清晰。
适用场景总结
- 如果你只是处理简单的ViewModel实例化,依赖容易提前获取,构造函数传参的写法足够用;
- 但如果需要用到
SavedStateHandle这类框架管理的对象、需要和Jetpack组件深度集成,或者依赖来源较深,CreationExtras能让你的代码更健壮、耦合度更低。
内容的提问来源于stack exchange,提问作者Felipe Ribeiro R. Magalhaes

