android - 使用 Hilt 进行依赖注入(inject)时,如何将运行时参数传递给 ViewModel 的构造函数?

标签 android android-fragments dependency-injection android-viewmodel dagger-hilt

我想知道如何在使用 Hilt 进行 DI 时将运行时参数传递给 ViewModel 的构造函数?在使用 Hilt 之前,我有一个如下所示的 ViewModel:

class ItemViewModel(private val itemId: Long) : ViewModel() {
    private val repo = ItemRepository(itemId) 
}

class ItemViewModelFactory(private val itemId: Long) : ViewModelProvider.Factory {
@Suppress("unchecked_cast")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
    if (modelClass.isAssignableFrom(ItemViewModel::class.java)) {
        return ItemViewModel(itemId) as T
    }
    throw IllegalArgumentException("Unknown ViewModel class")
}
我在我的 fragment 中创建了上面的 ViewModel,如下所示:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

    val args: ItemScreenFragmentArgs by navArgs()
    val itemId = args.itemId

    //Create the view model factory
    val viewModelFactory = ItemViewModelFactory(application, itemId)

    // Get a reference to the ViewModel associated with this fragment.
    val itemViewModel = ViewModelProvider(this, viewModelFactory).get(ItemViewModel::class.java)
}
如果我的 ItemViewModel 构造函数没有 itemId 参数,我使用 Hilt 的 ViewModel 和 Fragment 将如下所示:
class ItemViewModel
@ViewModelInject
constructor(private val repo: ItemRepository) : ViewModel() { }

@AndroidEntryPoint
class ItemFragment : Fragment() {
    private val itemViewModel: ItemViewModel by viewModels ()
}
我试图弄清楚如何将从 ItemFragment 的 NavArgs 获得的 itemId 传递给 ItemViewModel 的构造函数?有没有办法用 Hilt 做到这一点?

最佳答案

对于希望在使用 Dagger Hilt 时将运行时参数传递给 ViewModel 的其他任何人,我是这样做的:
我遵循 this example 中的代码它使用 AssistedInject图书馆。
我的代码现在如下所示:

class ItemViewModel
@AssistedInject
constructor(private val repo: ItemRepository, @Assisted private val itemId: Long) : ViewModel() {
    init {
        repo.itemId = itemId
    }

    @AssistedInject.Factory
    interface AssistedFactory {
        fun create(itemId: Long): ItemViewModel
    }

    companion object {
        fun provideFactory(
            assistedFactory: AssistedFactory,
            itemId: Long
        ): ViewModelProvider.Factory = object : ViewModelProvider.Factory {
            override fun <T : ViewModel?> create(modelClass: Class<T>): T {
                return assistedFactory.create(itemId) as T
            }
        }
    }
}

@InstallIn(FragmentComponent::class)
@AssistedModule
@Module
interface AssistedInjectModule {}

@AndroidEntryPoint
class ItemFragment : Fragment() {
    private val args: ItemScreenFragmentArgs by navArgs()      
    @Inject lateinit var itemViewModelAssistedFactory: ItemViewModel.AssistedFactory        
    private val itemViewModel: ItemViewModel by viewModels {
            ItemViewModel.provideFactory(itemViewModelAssistedFactory, args.itemId)
    }    
}

关于android - 使用 Hilt 进行依赖注入(inject)时,如何将运行时参数传递给 ViewModel 的构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65280323/

相关文章:

java - 在非 Web 应用程序中使用 @Autowired 时无法注入(inject)存储库

android - 从返回值设置 TextView

android - Maven actionbarsherlock - 主题资源不可用

android - 放置在 NavigationDrawer 顶部的 fragment

android - 从 xml 膨胀 android.support.v4.app.fragment 的正确方法

java - WebView 第二次显示黑屏?

android - 当我开始一个新线程时,我会强制关闭!

java - 从给定日期获取周一至周五的周日期

dependency-injection - symfony 3 传递给 [some service]::__construct() 的参数 1 必须是给定的 Doctrine\ORM\EntityRepository [something] 实例的实例

c# - ASP.NET Core DI 容器是否保证服务顺序?